diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 700c14e..9bfdc23 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,32 +4,31 @@ on: push: jobs: - Tests: strategy: matrix: - tox_env: [default, sqlmodel] + tox_env: [fastapi-pre121, fastapi-post121, sqlmodel] runs-on: ubuntu-latest steps: - - name: ๐Ÿ“ฅ checkout - uses: actions/checkout@v4 - - name: ๐Ÿ”ง setup tox-uv - uses: ./.github/tox-uv - - name: ๐Ÿงช tox -e ${{ matrix.tox_env }} - run: uv run tox -e ${{ matrix.tox_env }} - - name: "๐Ÿ” codecov: upload test coverage" - uses: codecov/codecov-action@v4.2.0 - with: - flags: ${{ matrix.tox_env }} - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + - name: ๐Ÿ“ฅ checkout + uses: actions/checkout@v4 + - name: ๐Ÿ”ง setup tox-uv + uses: ./.github/tox-uv + - name: ๐Ÿงช tox -e ${{ matrix.tox_env }} + run: uv run tox -e ${{ matrix.tox_env }} + - name: "๐Ÿ” codecov: upload test coverage" + uses: codecov/codecov-action@v4.2.0 + with: + flags: ${{ matrix.tox_env }} + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} Ruff: runs-on: ubuntu-latest steps: - - name: ๐Ÿ“ฅ checkout - uses: actions/checkout@v4 - - name: ๐Ÿ”ง setup uv - uses: ./.github/uv - - name: ๐Ÿถ ruff - run: uv run ruff check + - name: ๐Ÿ“ฅ checkout + uses: actions/checkout@v4 + - name: ๐Ÿ”ง setup uv + uses: ./.github/uv + - name: ๐Ÿถ ruff + run: uv run ruff check diff --git a/pyproject.toml b/pyproject.toml index f189b65..3b4490d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,6 +70,7 @@ dev = [ "aiosqlite>=0.20.0", "python-semantic-release>=9.8.8", "twine>=5.1.1", + "pdbpp>=0.11.7", ] [tool.uv.sources] @@ -100,15 +101,26 @@ mode = "init" changelog_file = "./docs/changelog.md" [tool.tox] -legacy_tox_ini = """ -[tox] -envlist = { default, sqlmodel } - -[testenv] -passenv = CI -runner = uv-venv-lock-runner -commands = - pytest --cov fastsqla --cov-report=term-missing --cov-report=xml -extras: - sqlmodel: sqlmodel -""" +envlist = ["sqlmodel", "fastapi-pre121", "fastapi-post121"] + +[tool.tox.env_run_base] +runner = "uv-venv-runner" +commands = [ + [ + "pytest", + "--cov", + "fastsqla", + "--cov-report=term-missing", + "--cov-report=xml", + ], +] +allowlist_externals = ["pytest", "pip"] + +[tool.tox.env.sqlmodel] +extras = ["sqlmodel"] + +[tool.tox.env.fastapi-pre121] +commands_pre = [["pip", "install", "-U", "fastapi<0.121"]] + +[tool.tox.env.fastapi-post121] +commands_pre = [["pip", "install", "-U", "fastapi>=0.121"]] diff --git a/src/fastsqla.py b/src/fastsqla.py index 594d401..dbb1ce3 100644 --- a/src/fastsqla.py +++ b/src/fastsqla.py @@ -4,7 +4,8 @@ from contextlib import _AsyncGeneratorContextManager, asynccontextmanager from typing import Annotated, Generic, TypeVar, TypedDict -from fastapi import Depends, FastAPI, Query +from fastapi import Depends as BaseDepends +from fastapi import FastAPI, Query from pydantic import BaseModel, Field from sqlalchemy import Result, Select, func, select from sqlalchemy.ext.asyncio import ( @@ -44,6 +45,15 @@ logger = get_logger(__name__) +def Depends(*args, **kwargs): + "Allow backward compatibility with fastapi<0.121" + try: + return BaseDepends(*args, **kwargs) + except TypeError: + kwargs.pop("scope") + return BaseDepends(*args, **kwargs) + + class Base(DeclarativeBase, DeferredReflection): """Inherit from `Base` to declare an `SQLAlchemy` model. @@ -252,7 +262,7 @@ async def new_session() -> AsyncGenerator[AsyncSession, None]: yield session -Session = Annotated[AsyncSession, Depends(new_session)] +Session = Annotated[AsyncSession, Depends(new_session, scope="function")] """Dependency used exclusively in endpoints to get an `SQLAlchemy` or `SQLModel` session. `Session` is a [`FastAPI` dependency](https://fastapi.tiangolo.com/tutorial/dependencies/) diff --git a/uv.lock b/uv.lock index 7975dce..ee708d8 100644 --- a/uv.lock +++ b/uv.lock @@ -274,6 +274,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d6/a9/3bdbd257f7aa3cb971bbf8c688827532ecfe6448168d211cb63b942f6431/Faker-28.4.1-py3-none-any.whl", hash = "sha256:e59c01d1e8b8e20a83255ab8232c143cb2af3b4f5ab6a3f5ce495f385ad8ab4c", size = 1834900, upload-time = "2024-09-04T14:38:49.657Z" }, ] +[[package]] +name = "fancycompleter" +version = "0.11.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyreadline3", marker = "python_full_version < '3.13' and sys_platform == 'win32'" }, + { name = "pyrepl", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4e/4c/d11187dee93eff89d082afda79b63c79320ae1347e49485a38f05ad359d0/fancycompleter-0.11.1.tar.gz", hash = "sha256:5b4ad65d76b32b1259251516d0f1cb2d82832b1ff8506697a707284780757f69", size = 341776, upload-time = "2025-05-26T12:59:11.045Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/c3/6f0e3896f193528bbd2b4d2122d4be8108a37efab0b8475855556a8c4afa/fancycompleter-0.11.1-py3-none-any.whl", hash = "sha256:44243d7fab37087208ca5acacf8f74c0aa4d733d04d593857873af7513cdf8a6", size = 11207, upload-time = "2025-05-26T12:59:09.857Z" }, +] + [[package]] name = "fastapi" version = "0.115.6" @@ -290,7 +303,7 @@ wheels = [ [[package]] name = "fastsqla" -version = "0.4.3" +version = "0.4.6" source = { editable = "." } dependencies = [ { name = "fastapi" }, @@ -316,6 +329,7 @@ dev = [ { name = "coverage" }, { name = "faker" }, { name = "httpx" }, + { name = "pdbpp" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, @@ -346,6 +360,7 @@ dev = [ { name = "coverage", specifier = ">=7.6.1" }, { name = "faker", specifier = ">=28.4.1" }, { name = "httpx", specifier = ">=0.27.2" }, + { name = "pdbpp", specifier = ">=0.11.7" }, { name = "pytest", specifier = ">=8.3.2" }, { name = "pytest-asyncio", specifier = ">=0.24.0" }, { name = "pytest-cov", specifier = ">=5.0.0" }, @@ -870,6 +885,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, ] +[[package]] +name = "pdbpp" +version = "0.11.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fancycompleter" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c6/4c/118ef9534ac0632859b48c305d8c5dc9d6f963564fdfa66bc785c560247c/pdbpp-0.11.7.tar.gz", hash = "sha256:cb6604ac31a35ed0f2a29650a8c022b26284620be3e01cfd41b683b91da1ff14", size = 76026, upload-time = "2025-07-18T09:36:02.781Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/e9/704bbc08aace64fee536e4c2c20f63f64f6fdbad72938c5ed46c9723a9f1/pdbpp-0.11.7-py3-none-any.whl", hash = "sha256:51916b63693898cf4881b36b4501c83947758d73f582f1f84893662b163bdb75", size = 30545, upload-time = "2025-07-18T09:36:01.478Z" }, +] + [[package]] name = "platformdirs" version = "4.3.6" @@ -969,6 +997,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/09/fb/79a8d27966e90feeeb686395c8b1bff8221727abcbd80d2485841393a955/pymdown_extensions-10.14.1-py3-none-any.whl", hash = "sha256:637951cbfbe9874ba28134fb3ce4b8bcadd6aca89ac4998ec29dcbafd554ae08", size = 264283, upload-time = "2025-01-22T01:15:05.155Z" }, ] +[[package]] +name = "pyreadline3" +version = "3.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/49/4cea918a08f02817aabae639e3d0ac046fef9f9180518a3ad394e22da148/pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7", size = 99839, upload-time = "2024-09-19T02:40:10.062Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/dc/491b7661614ab97483abf2056be1deee4dc2490ecbf7bff9ab5cdbac86e1/pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6", size = 83178, upload-time = "2024-09-19T02:40:08.598Z" }, +] + +[[package]] +name = "pyrepl" +version = "0.11.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/08/4f/7088417e5465c53a30b918d30542aad89352ea0d635a5d077717c69a7d2b/pyrepl-0.11.4.tar.gz", hash = "sha256:efe988b4a6e5eed587e9769dc2269aeec2b6feec2f5d77995ee85b9ad7cf7063", size = 51089, upload-time = "2025-07-17T22:56:25.42Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/a5/ce97a778f096aaa27cfcb7ad09f1198cf73277dcab6c68a4b8f332d91e48/pyrepl-0.11.4-py3-none-any.whl", hash = "sha256:ac30d6340267a21c39e1b1934f92bca6b8735017d14b17e40f903b2d1563541d", size = 55596, upload-time = "2025-07-17T22:56:24.537Z" }, +] + [[package]] name = "pytest" version = "8.3.2"