Skip to content

Commit 82651fe

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into replace-pytz
2 parents 6655a0b + a725917 commit 82651fe

File tree

15 files changed

+646
-445
lines changed

15 files changed

+646
-445
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
TORTOISE_MSSQL_DRIVER: ODBC Driver 18 for SQL Server
4646
strategy:
4747
matrix:
48-
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
48+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
4949
steps:
5050
- uses: actions/cache@v4
5151
with:
@@ -65,7 +65,7 @@ jobs:
6565
sudo apt-get update
6666
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18
6767
- name: Run ci
68-
run: uv run make ci
68+
run: make ci
6969
- name: Test FastAPI/Blacksheep Example
7070
run: |
7171
PYTHONPATH=$DEST_FASTAPI uv run pytest $PYTEST_ARGS $DEST_FASTAPI/_tests.py

.github/workflows/gh-pages-release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
python-version: "3.9"
1414
- uses: astral-sh/setup-uv@v6
1515
- name: Build docs
16-
run: uv run make docs
16+
run: make docs
1717
- name: Deploy release docs
1818
uses: peaceiris/actions-gh-pages@v3
1919
with:

.github/workflows/gh-pages.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
python-version: "3.9"
1515
- uses: astral-sh/setup-uv@v6
1616
- name: Build docs
17-
run: uv run make docs
17+
run: make docs
1818
- name: Deploy latest docs
1919
uses: peaceiris/actions-gh-pages@v3
2020
with:

CHANGELOG.rst

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,36 @@ Changelog
1111
====
1212

1313
0.26.0 (unreleased)
14-
-------------------
15-
Added
14+
-------------------
15+
16+
0.25
17+
====
18+
19+
0.25.3
20+
------
21+
Fixed
1622
^^^^^
17-
- Add `create()` method to reverse ForeignKey relations, enabling `parent.children.create()` syntax
23+
- Fix exception when creating aiosqlite connections on aiosqlite==0.22.0 (#2035)
24+
- Fix implicit anyio dependency introduced, but not declared (#2045)
1825

26+
0.25.2
27+
------
1928
Fixed
2029
^^^^^
21-
- Fix sqlite decimal filter error with `__gt` (#2020)
30+
- Fix grouping by in subqueries (#2021)
31+
- Fix sqlite decimal filter error with `__gt` (#2019)
32+
33+
Changed
34+
^^^^^
35+
- Official support python3.14 (#2026)
36+
- Migrate from poetry to uv (#1987)
37+
- Reorder imports by ruff (#1966)
38+
- Migrate lint tool from isort+black to ruff (#1963)
39+
40+
Added
41+
^^^^^
42+
- Add `create()` method to reverse ForeignKey relations, enabling `parent.children.create()` syntax (#1991)
2243

23-
0.25
24-
====
2544

2645
0.25.1
2746
------------------

Makefile

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,25 @@ help:
2121
@echo " lint Auto-formats the code and check type hints"
2222

2323
up:
24-
@uv lock --upgrade
24+
uv lock --upgrade
2525

2626
deps:
27-
@uv sync --all-groups --extra asyncpg --extra accel --extra psycopg --extra asyncodbc --extra aiomysql $(options)
27+
uv sync --frozen --all-groups --extra asyncpg --extra accel --extra psycopg --extra asyncodbc --extra aiomysql $(options)
2828

2929
deps_with_asyncmy:
30-
@uv sync --all-groups --extra asyncpg --extra accel --extra psycopg --extra asyncodbc --extra asyncmy $(options)
30+
uv sync --frozen --all-groups --extra asyncpg --extra accel --extra psycopg --extra asyncodbc --extra asyncmy $(options)
3131

3232
check: build _check
3333
_check:
34-
ruff format --check $(checkfiles) || (echo "Please run 'make style' to auto-fix style issues" && false)
35-
ruff check $(checkfiles)
34+
uv run --frozen ruff format --check $(checkfiles) || (echo "Please run 'make style' to auto-fix style issues" && false)
35+
uv run --frozen ruff check $(checkfiles)
3636
#pylint -d C,W,R $(checkfiles)
3737
$(MAKE) _codeqc
3838

3939
style: deps _style
4040
_style:
41-
ruff format $(checkfiles)
42-
ruff check --fix $(checkfiles)
41+
uv run --frozen ruff format $(checkfiles)
42+
uv run --frozen ruff check --fix $(checkfiles)
4343

4444
lint: build _lint
4545
_lint:
@@ -48,30 +48,30 @@ _lint:
4848

4949
codeqc: build _codeqc
5050
_codeqc:
51-
mypy $(checkfiles)
52-
bandit -c pyproject.toml -r $(checkfiles)
53-
twine check dist/*
51+
uv run --frozen mypy $(checkfiles)
52+
uv run --frozen bandit -c pyproject.toml -r $(checkfiles)
53+
uv run --frozen twine check dist/*
5454

5555
test: deps
56-
$(py_warn) TORTOISE_TEST_DB=sqlite://:memory: pytest $(pytest_opts)
56+
$(py_warn) TORTOISE_TEST_DB=sqlite://:memory: uv run --frozen pytest $(pytest_opts)
5757

5858
test_sqlite:
59-
$(py_warn) TORTOISE_TEST_DB=sqlite://:memory: pytest --cov-report= $(pytest_opts)
59+
$(py_warn) TORTOISE_TEST_DB=sqlite://:memory: uv run --frozen pytest --cov-report= $(pytest_opts)
6060

6161
test_sqlite_regexp:
62-
$(py_warn) TORTOISE_TEST_DB=sqlite://:memory:?install_regexp_functions=True pytest --cov-report= $(pytest_opts)
62+
$(py_warn) TORTOISE_TEST_DB=sqlite://:memory:?install_regexp_functions=True uv run --frozen pytest --cov-report= $(pytest_opts)
6363

6464
test_postgres_asyncpg:
65-
python -V | grep PyPy || $(py_warn) TORTOISE_TEST_DB="asyncpg://postgres:$(TORTOISE_POSTGRES_PASS)@127.0.0.1:5432/test_\{\}" pytest $(pytest_opts) --cov-report=
65+
uv run --frozen python -V | grep PyPy || $(py_warn) TORTOISE_TEST_DB="asyncpg://postgres:$(TORTOISE_POSTGRES_PASS)@127.0.0.1:5432/test_\{\}" uv run --frozen pytest $(pytest_opts) --cov-report=
6666

6767
test_postgres_psycopg:
68-
python -V | grep PyPy || $(py_warn) TORTOISE_TEST_DB="psycopg://postgres:$(TORTOISE_POSTGRES_PASS)@127.0.0.1:5432/test_\{\}" pytest $(pytest_opts) --cov-report=
68+
uv run --frozen python -V | grep PyPy || $(py_warn) TORTOISE_TEST_DB="psycopg://postgres:$(TORTOISE_POSTGRES_PASS)@127.0.0.1:5432/test_\{\}" uv run --frozen pytest $(pytest_opts) --cov-report=
6969

7070
test_mysql_myisam:
71-
$(py_warn) TORTOISE_TEST_DB="mysql://root:$(TORTOISE_MYSQL_PASS)@127.0.0.1:3306/test_\{\}?storage_engine=MYISAM" pytest $(pytest_opts) --cov-report=
71+
$(py_warn) TORTOISE_TEST_DB="mysql://root:$(TORTOISE_MYSQL_PASS)@127.0.0.1:3306/test_\{\}?storage_engine=MYISAM" uv run --frozen pytest $(pytest_opts) --cov-report=
7272

7373
test_mysql:
74-
$(py_warn) TORTOISE_TEST_DB="mysql://root:$(TORTOISE_MYSQL_PASS)@127.0.0.1:3306/test_\{\}" pytest $(pytest_opts) --cov-report=
74+
$(py_warn) TORTOISE_TEST_DB="mysql://root:$(TORTOISE_MYSQL_PASS)@127.0.0.1:3306/test_\{\}" uv run --frozen pytest $(pytest_opts) --cov-report=
7575

7676
test_mysql_asyncmy:
7777
$(MAKE) deps_with_asyncmy
@@ -80,26 +80,26 @@ test_mysql_asyncmy:
8080
$(MAKE) deps
8181

8282
test_mssql:
83-
$(py_warn) TORTOISE_TEST_DB="mssql://sa:$(TORTOISE_MSSQL_PASS)@127.0.0.1:1433/test_\{\}?driver=$(TORTOISE_MSSQL_DRIVER)&TrustServerCertificate=YES" pytest $(pytest_opts) --cov-report=
83+
$(py_warn) TORTOISE_TEST_DB="mssql://sa:$(TORTOISE_MSSQL_PASS)@127.0.0.1:1433/test_\{\}?driver=$(TORTOISE_MSSQL_DRIVER)&TrustServerCertificate=YES" uv run --frozen pytest $(pytest_opts) --cov-report=
8484

8585
test_oracle:
86-
$(py_warn) TORTOISE_TEST_DB="oracle://SYSTEM:$(TORTOISE_ORACLE_PASS)@127.0.0.1:1521/test_\{\}?driver=$(TORTOISE_ORACLE_DRIVER)" pytest $(pytest_opts) --cov-report=
86+
$(py_warn) TORTOISE_TEST_DB="oracle://SYSTEM:$(TORTOISE_ORACLE_PASS)@127.0.0.1:1521/test_\{\}?driver=$(TORTOISE_ORACLE_DRIVER)" uv run --frozen pytest $(pytest_opts) --cov-report=
8787

8888
_testall: test_sqlite test_postgres_asyncpg test_postgres_psycopg test_mysql_myisam test_mysql test_mysql_asyncmy test_mssql
8989

90-
coverage report
90+
uv run --frozen coverage report
9191

9292
testall: deps _testall
9393

9494
ci: check _testall
9595

9696
docs: deps
9797
rm -fR ./build
98-
sphinx-build -M html docs build
98+
uv run --frozen sphinx-build -M html docs build
9999

100100
build: deps
101101
rm -fR dist/
102102
uv build
103103

104104
publish: deps _build
105-
twine upload dist/*
105+
uv run --frozen twine upload dist/*

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ keywords = ["sql", "mysql", "postgres", "psql", "sqlite", "aiosqlite", "asyncpg"
88
dynamic = [ "version" ]
99
requires-python = ">=3.9"
1010
dependencies = [
11-
"pypika-tortoise (>=0.6.1,<1.0.0)",
11+
"pypika-tortoise (>=0.6.3,<1.0.0)",
1212
"iso8601 (>=2.1.0,<3.0.0); python_version < '4.0'",
1313
"aiosqlite (>=0.16.0,<1.0.0)",
14+
"anyio",
15+
"typing-extensions (>= 4.1.0); python_version < '3.11'",
1416
]
1517
classifiers = [
1618
"License :: OSI Approved :: Apache Software License",
@@ -22,6 +24,7 @@ classifiers = [
2224
"Programming Language :: Python :: 3.11",
2325
"Programming Language :: Python :: 3.12",
2426
"Programming Language :: Python :: 3.13",
27+
"Programming Language :: Python :: 3.14",
2528
"Programming Language :: Python :: Implementation :: CPython",
2629
"Programming Language :: Python :: Implementation :: PyPy",
2730
"Programming Language :: PL/SQL",

tests/contrib/test_decorator.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
class TestDecorator(test.TestCase):
99
@test.requireCapability(dialect="sqlite")
1010
async def test_script_with_init_memory_sqlite(self) -> None:
11-
r = subprocess.run(["python", "examples/basic.py"], capture_output=True) # nosec
12-
output = r.stdout.decode()
11+
r = subprocess.run(["python", "examples/basic.py"], capture_output=True, text=True) # nosec
12+
assert not r.stderr
13+
output = r.stdout
1314
s = "[{'id': 1, 'name': 'Updated name'}, {'id': 2, 'name': 'Test 2'}]"
1415
self.assertIn(s, output)
1516

tests/test_group_by.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from tests.testmodels import Author, Book, Event, Team, Tournament
22
from tortoise.contrib import test
3+
from tortoise.expressions import Subquery
34
from tortoise.functions import Avg, Count, Sum, Upper
45

56

@@ -317,3 +318,14 @@ async def test_group_by_nested_column(self):
317318
async def test_group_by_id_with_nested_filter(self):
318319
ret = await Book.filter(author__name="author1").group_by("id").values_list("id")
319320
self.assertEqual(set(ret), {(book.id,) for book in self.books1})
321+
322+
async def test_select_subquery_with_group_by(self):
323+
subquery = Subquery(
324+
Book.all().group_by("rating").order_by("-rating").limit(1).values("rating")
325+
)
326+
ret = (
327+
await Author.annotate(top_rating=subquery)
328+
.order_by("id")
329+
.values_list("name", "top_rating")
330+
)
331+
self.assertEqual(ret, [(self.a1.name, 9.0), (self.a2.name, 9.0)])

tests/test_table_name.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,7 @@ async def test_glabal_name_generator(self):
3636

3737
async def test_custom_table_name_precedence(self):
3838
self.assertEqual(CustomTable._meta.db_table, "my_custom_table")
39+
40+
async def _tearDownDB(self) -> None:
41+
# Explicitly close aiosqlite connection to fix ResourceWarning
42+
await Tortoise.get_connection("default").close()

tests/utils/test_describe_model.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import json
4+
import sys
45
import uuid
56
from typing import Union
67

@@ -29,6 +30,18 @@
2930
OneToOneFieldInstance,
3031
)
3132

33+
if sys.version_info >= (3, 14):
34+
35+
def union_annotation(x: str, y: str) -> str:
36+
return f"{x} | {y}"
37+
else:
38+
39+
def union_annotation(x: str, y: str) -> str:
40+
return f"Union[{x}, {y}]"
41+
42+
43+
UNION_DICT_LIST = union_annotation("dict", "list")
44+
3245

3346
class TestDescribeModels(test.TestCase):
3447
def test_describe_models_all_serializable(self):
@@ -1366,7 +1379,7 @@ def test_describe_model_json(self):
13661379
"oracle": "NCLOB",
13671380
"postgres": "JSONB",
13681381
},
1369-
"python_type": "Union[dict, list]",
1382+
"python_type": UNION_DICT_LIST,
13701383
"generated": False,
13711384
"nullable": False,
13721385
"unique": False,
@@ -1386,7 +1399,7 @@ def test_describe_model_json(self):
13861399
"oracle": "NCLOB",
13871400
"postgres": "JSONB",
13881401
},
1389-
"python_type": "Union[dict, list]",
1402+
"python_type": UNION_DICT_LIST,
13901403
"generated": False,
13911404
"nullable": True,
13921405
"unique": False,
@@ -1406,7 +1419,7 @@ def test_describe_model_json(self):
14061419
"oracle": "NCLOB",
14071420
"postgres": "JSONB",
14081421
},
1409-
"python_type": "Union[dict, list]",
1422+
"python_type": UNION_DICT_LIST,
14101423
"generated": False,
14111424
"nullable": False,
14121425
"unique": False,
@@ -1426,7 +1439,7 @@ def test_describe_model_json(self):
14261439
"oracle": "NCLOB",
14271440
"postgres": "JSONB",
14281441
},
1429-
"python_type": "Union[dict, list]",
1442+
"python_type": UNION_DICT_LIST,
14301443
"generated": False,
14311444
"nullable": True,
14321445
"unique": False,

0 commit comments

Comments
 (0)