Skip to content

Commit 3f9a6d9

Browse files
committed
Fix merge conflict
2 parents 02776d8 + 08c2421 commit 3f9a6d9

File tree

13 files changed

+617
-431
lines changed

13 files changed

+617
-431
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: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,33 @@ Changelog
1111
====
1212

1313
0.26.0 (unreleased)
14-
-------------------
15-
Added
16-
^^^^^
17-
- Add `create()` method to reverse ForeignKey relations, enabling `parent.children.create()` syntax
18-
14+
-------------------
1915
Fixed
2016
^^^^^
21-
- Fix sqlite decimal filter error with `__gt` (#2020)
17+
- Fix exception when creating aiosqlite connections on aiosqlite==0.22.0 (#2035)
2218

2319
0.25
2420
====
2521

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

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
"aiosqlite (>=0.16.0,<1.0.0)",
1313
"pytz",
14+
# Typing support for older Python
15+
"typing-extensions (>= 4.1.0)",
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/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,

tortoise/__init__.py

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

3-
import asyncio
43
import importlib
54
import json
65
import logging
@@ -12,6 +11,7 @@
1211
from types import ModuleType
1312
from typing import Any, cast
1413

14+
from anyio import from_thread
1515
from pypika_tortoise import Query, Table
1616

1717
from tortoise.backends.base.client import BaseDBAsyncClient
@@ -637,14 +637,18 @@ async def do_stuff():
637637
638638
run_async(do_stuff())
639639
"""
640-
loop = asyncio.get_event_loop()
641-
try:
642-
loop.run_until_complete(coro)
643-
finally:
644-
loop.run_until_complete(connections.close_all(discard=True))
640+
641+
async def main() -> None:
642+
try:
643+
await coro
644+
finally:
645+
await connections.close_all(discard=True)
646+
647+
with from_thread.start_blocking_portal() as portal:
648+
portal.call(main)
645649

646650

647-
__version__ = "0.25.1"
651+
__version__ = "0.25.2"
648652

649653
__all__ = [
650654
"Model",

0 commit comments

Comments
 (0)