Skip to content

Commit b73a90b

Browse files
authored
Merge branch 'kayak:master' into master
2 parents e49bb6e + 1c9646f commit b73a90b

38 files changed

+1260
-148
lines changed

.github/workflows/black.yml

-12
This file was deleted.

.github/workflows/pythonpackage.yml renamed to .github/workflows/ci.yml

+16-12
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,36 @@
1-
name: Unit Tests
1+
name: CI
22

33
on:
44
push:
5-
branches: ["master"]
65
pull_request:
7-
branches: ["master"]
6+
workflow_dispatch:
87

98
jobs:
10-
test:
9+
lint:
10+
name: Lint
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: actions/setup-python@v5
15+
- uses: pre-commit/[email protected]
1116

17+
test:
18+
name: Unit Tests
1219
runs-on: ubuntu-latest
1320
strategy:
14-
max-parallel: 4
21+
max-parallel: 5
1522
matrix:
16-
python-version: [3.6, 3.7, 3.8, 3.9]
23+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
1724

1825
steps:
19-
- uses: actions/checkout@v1
26+
- uses: actions/checkout@v4
2027
- name: Set up Python ${{ matrix.python-version }}
21-
uses: actions/setup-python@v1
28+
uses: actions/setup-python@v5
2229
with:
2330
python-version: ${{ matrix.python-version }}
2431

2532
- name: Install dependencies
26-
run: |
27-
python -m pip install --upgrade pip
28-
pip install -r requirements-dev.txt
29-
pip install "coveralls<3.0.0"
33+
run: python -m pip install -U pip -r requirements-dev.txt "coveralls<3.0.0"
3034

3135
- name: Run test suite
3236
env:

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ target/
7070
# virtualenv
7171
venv/
7272
ENV/
73+
.venv/
7374

7475
# OS X
7576
.DS_Store

.pre-commit-config.yaml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
exclude: '.git'
2+
default_stages: [commit]
3+
fail_fast: false
4+
5+
repos:
6+
- repo: https://github.com/pre-commit/pre-commit-hooks
7+
rev: v4.4.0
8+
hooks:
9+
- id: trailing-whitespace
10+
files: "pypika.*"
11+
exclude: ".*json$|.*txt$|.*csv|.*md|.*svg"
12+
- id: check-yaml
13+
- id: no-commit-to-branch
14+
args: ['--branch', 'master']
15+
- id: check-merge-conflict
16+
- id: check-ast
17+
- id: check-json
18+
- id: check-toml
19+
- id: check-yaml
20+
- id: debug-statements
21+
22+
- repo: https://github.com/psf/black
23+
rev: 23.9.1
24+
hooks:
25+
- id: black

CONTRIBUTING.rst

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
Guidelines for Contributing
2+
===========================
3+
4+
PyPika welcomes contributions in all forms. These may be bugs, feature requests, documentation, or examples. Please feel free to:
5+
6+
#. Submitting an issue
7+
#. Opening a pull request
8+
#. Helping with outstanding issues and pull requests
9+
10+
Open an issue
11+
-------------
12+
13+
If you find a bug or have a feature request, please `open an issue <https://github.com/kayak/pypika/issues>`_ on GitHub. Please just check that the issue doesn't already exist before opening a new one.
14+
15+
Local development steps
16+
-----------------------
17+
18+
Create a forked branch of the repo
19+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
Do this once but keep it up to date
22+
23+
#. `Fork the kayak/PyPika repo GitHub <https://github.com/kayak/pypika/fork>`_
24+
#. Clone forked repo and set upstream
25+
26+
.. code-block:: bash
27+
28+
git clone [email protected]:<your-username>/pypika.git
29+
cd pypika
30+
git remote add upstream [email protected]:kayak/pypika.git
31+
32+
Setup local development environment
33+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34+
35+
#. Setup up python virtual environment
36+
37+
Create and activate the environment. Here is an example using ``venv`` from the standard library:
38+
39+
.. code-block:: bash
40+
41+
python -m venv .venv
42+
source .venv/bin/activate
43+
44+
#. Install python dependencies for development
45+
46+
With the virtual environment activated, install the development requirements, pre-commit, and the package itself:
47+
48+
.. code-block:: bash
49+
50+
make install
51+
52+
#. Run the tests
53+
54+
The unit tests are run with ``unittest`` via ``tox``. To run the tests locally:
55+
56+
.. code-block:: bash
57+
58+
make test
59+
60+
These tests will also run on GitHub Actions when you open a pull request.
61+
62+
#. Build the docs locally
63+
64+
Our docs are built with Sphinx. To build the docs locally:
65+
66+
.. code-block:: bash
67+
68+
make docs.build
69+
70+
Open the docs in your browser. For instance, on macOS:
71+
72+
.. code-block:: bash
73+
74+
open docs/_build/index.html
75+
76+
Pull Request checklist
77+
----------------------
78+
79+
Please check that your pull request meets the following criteria:
80+
81+
- Unit tests pass
82+
- pre-commit hooks pass
83+
- Docstring and examples and checking for correct render in the docs
84+
85+
Documentation
86+
-------------
87+
88+
Documentation is built with Sphinx and hosted on `Read the Docs <https://pypika.readthedocs.io/en/latest/>`_. The latest builds are displayed on their site `here <https://readthedocs.org/projects/pypika/builds/>`_.
89+
90+
The code documentation is to be written in the docstrings of the code itself or in the various ``.rst`` files in project root or the ``docs/`` directory.
91+
92+
The docstrings can be in either `Numpy <https://numpydoc.readthedocs.io/en/latest/format.html>`_ or `Sphinx <https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html>`_ format.
93+
94+
Automations
95+
-----------
96+
97+
We use `pre-commit <https://pre-commit.com/>`_ to automate format checks. Install the pre-commit hooks with the ``make install`` command described above.
98+
99+
GitHub Actions runs both format checks and unit tests on every pull request.
100+
101+
**NOTE:** The hosted documentation is built separately from the GitHub Actions workflow. To build the docs locally, use the ``make docs.build`` command described above.

Makefile

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# You can set these variables from the command line.
2+
SPHINXBUILD = sphinx-build
3+
SOURCEDIR = docs
4+
BUILDDIR = docs/_build
5+
6+
7+
help: ## Show this help.
8+
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'
9+
10+
install: ## Install development dependencies
11+
pip install -r requirements-dev.txt pre-commit -e .
12+
pre-commit install
13+
14+
test: ## Run tests
15+
tox
16+
17+
docs.build: ## Build the documentation
18+
$(SPHINXBUILD) $(SOURCEDIR) $(BUILDDIR) -b html -E
19+
@echo
20+
@echo "Build finished. The HTML pages are in $(BUILDDIR)."
21+
22+
docs.clean: ## Remove the generated documentation
23+
rm -rf $(BUILDDIR)

README.rst

+156-2
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ Example of a correlated subquery in the `SELECT`
510510
Unions
511511
""""""
512512

513-
Both ``UNION`` and ``UNION ALL`` are supported. ``UNION DISTINCT`` is synonomous with "UNION`` so |Brand| does not
513+
Both ``UNION`` and ``UNION ALL`` are supported. ``UNION DISTINCT`` is synonymous with ``UNION`` so |Brand| does not
514514
provide a separate function for it. Unions require that queries have the same number of ``SELECT`` clauses so
515515
trying to cast a unioned query to string will throw a ``SetOperationException`` if the column sizes are mismatched.
516516

@@ -1274,12 +1274,166 @@ This produces:
12741274
12751275
CREATE TABLE "names" AS (SELECT "last_name","first_name" FROM "person")
12761276
1277+
Managing Table Indices
1278+
^^^^^^^^^^^^^^^^^^^^^^
1279+
1280+
Create Indices
1281+
""""""""""""""""
1282+
1283+
The entry point for creating indices is ``pypika.Query.create_index``.
1284+
An index name (as ``str``) or a ``pypika.terms.Index`` a table (as ``str`` or ``pypika.Table``) and
1285+
columns (as ``pypika.Column``) must be specified.
1286+
1287+
.. code-block:: python
1288+
1289+
my_index = Index("my_index")
1290+
person = Table("person")
1291+
stmt = Query \
1292+
.create_index(my_index) \
1293+
.on(person) \
1294+
.columns(person.first_name, person.last_name)
1295+
1296+
This produces:
1297+
1298+
.. code-block:: sql
1299+
1300+
CREATE INDEX my_index
1301+
ON person (first_name, last_name)
1302+
1303+
It is also possible to create a unique index
1304+
1305+
.. code-block:: python
1306+
1307+
my_index = Index("my_index")
1308+
person = Table("person")
1309+
stmt = Query \
1310+
.create_index(my_index) \
1311+
.on(person) \
1312+
.columns(person.first_name, person.last_name) \
1313+
.unique()
1314+
1315+
This produces:
1316+
1317+
.. code-block:: sql
1318+
1319+
CREATE UNIQUE INDEX my_index
1320+
ON person (first_name, last_name)
1321+
1322+
It is also possible to create an index if it does not exist
1323+
1324+
.. code-block:: python
1325+
1326+
my_index = Index("my_index")
1327+
person = Table("person")
1328+
stmt = Query \
1329+
.create_index(my_index) \
1330+
.on(person) \
1331+
.columns(person.first_name, person.last_name) \
1332+
.if_not_exists()
1333+
1334+
This produces:
1335+
1336+
.. code-block:: sql
1337+
1338+
CREATE INDEX IF NOT EXISTS my_index
1339+
ON person (first_name, last_name)
1340+
1341+
Drop Indices
1342+
""""""""""""""""
1343+
1344+
Then entry point for dropping indices is ``pypika.Query.drop_index``.
1345+
It takes either ``str`` or ``pypika.terms.Index`` as an argument.
1346+
1347+
.. code-block:: python
1348+
1349+
my_index = Index("my_index")
1350+
stmt = Query.drop_index(my_index)
1351+
1352+
This produces:
1353+
1354+
.. code-block:: sql
1355+
1356+
DROP INDEX my_index
1357+
1358+
It is also possible to drop an index if it exists
1359+
1360+
.. code-block:: python
1361+
1362+
my_index = Index("my_index")
1363+
stmt = Query.drop_index(my_index).if_exists()
1364+
1365+
This produces:
1366+
1367+
.. code-block:: sql
1368+
1369+
DROP INDEX IF EXISTS my_index
1370+
1371+
1372+
Chaining Functions
1373+
^^^^^^^^^^^^^^^^^^
1374+
1375+
The ``QueryBuilder.pipe`` method gives a more readable alternative while chaining functions.
1376+
1377+
.. code-block:: python
1378+
1379+
# This
1380+
(
1381+
query
1382+
.pipe(func1, *args)
1383+
.pipe(func2, **kwargs)
1384+
.pipe(func3)
1385+
)
1386+
1387+
# Is equivalent to this
1388+
func3(func2(func1(query, *args), **kwargs))
1389+
1390+
Or for a more concrete example:
1391+
1392+
.. code-block:: python
1393+
1394+
from pypika import Field, Query, functions as fn
1395+
from pypika.queries import QueryBuilder
1396+
1397+
def filter_days(query: QueryBuilder, col, num_days: int) -> QueryBuilder:
1398+
if isinstance(col, str):
1399+
col = Field(col)
1400+
1401+
return query.where(col > fn.Now() - num_days)
1402+
1403+
def count_groups(query: QueryBuilder, *groups) -> QueryBuilder:
1404+
return query.groupby(*groups).select(*groups, fn.Count("*").as_("n_rows"))
1405+
1406+
base_query = Query.from_("table")
1407+
1408+
query = (
1409+
base_query
1410+
.pipe(filter_days, "date", num_days=7)
1411+
.pipe(count_groups, "col1", "col2")
1412+
)
1413+
1414+
This produces:
1415+
1416+
.. code-block:: sql
1417+
1418+
SELECT "col1","col2",COUNT(*) n_rows
1419+
FROM "table"
1420+
WHERE "date">NOW()-7
1421+
GROUP BY "col1","col2"
1422+
12771423
.. _tutorial_end:
12781424

1425+
.. _contributing_start:
12791426

1280-
.. _license_start:
1427+
Contributing
1428+
------------
1429+
1430+
We welcome community contributions to |Brand|. Please see the `contributing guide <6_contributing.html>`_ to more info.
1431+
1432+
.. _contributing_end:
12811433

12821434

1435+
.. _license_start:
1436+
12831437
License
12841438
-------
12851439

0 commit comments

Comments
 (0)