From 0f3609c7973c4a80587b0097fe0a076f5928d98c Mon Sep 17 00:00:00 2001 From: Vittorio Zamboni Date: Mon, 27 Jun 2022 10:54:50 +0100 Subject: [PATCH 01/31] Changed Collection inner class to Settings (#3) --- fastapi_users_db_beanie/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index 2ed9a9f..c8d982a 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -22,7 +22,7 @@ class BeanieBaseUser(Generic[ID], Document): is_superuser: bool = False is_verified: bool = False - class Collection: + class Settings: email_collation = Collation("en", strength=2) indexes = [ IndexModel("email", unique=True), @@ -69,7 +69,7 @@ async def get_by_email(self, email: str) -> Optional[UP_BEANIE]: """Get a single user by email.""" return await self.user_model.find_one( self.user_model.email == email, - collation=self.user_model.Collection.email_collation, + collation=self.user_model.Settings.email_collation, ) async def get_by_oauth_account( From 4dd88c392ae47c4952b6e4714a864be34c96e2c7 Mon Sep 17 00:00:00 2001 From: Vittorio Zamboni Date: Mon, 27 Jun 2022 10:55:52 +0100 Subject: [PATCH 02/31] Replace get_event_loop with single methods in conftest (#4) --- tests/conftest.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index cd94089..37435ca 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,8 +6,16 @@ @pytest.fixture(scope="session") def event_loop(): - """Force the pytest-asyncio loop to be the main one.""" - loop = asyncio.get_event_loop() + """ + Force the pytest-asyncio loop to be the main one. + If there is no running event loop, create one and + set as the current one. + """ + try: + loop = asyncio.get_running_loop() + except RuntimeError: + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) yield loop From 347e9ec012b933dbc1fa2d9e7ac84045eee688f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Mon, 27 Jun 2022 11:58:26 +0200 Subject: [PATCH 03/31] =?UTF-8?q?Bump=20version:=201.1.0=20=E2=86=92=201.1?= =?UTF-8?q?.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi_users_db_beanie/__init__.py | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index c8d982a..e71511d 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -10,7 +10,7 @@ from pymongo import IndexModel from pymongo.collation import Collation -__version__ = "1.1.0" +__version__ = "1.1.1" class BeanieBaseUser(Generic[ID], Document): diff --git a/setup.cfg b/setup.cfg index abcd2e3..b26df6a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.1.0 +current_version = 1.1.1 commit = True tag = True From 15498c5cb53d9da187c252a412f0bc035d26f71b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Mon, 18 Jul 2022 11:00:14 +0200 Subject: [PATCH 04/31] Update FUNDING.yml --- .github/FUNDING.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index d4860d5..332f3ca 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1 @@ -# These are supported funding model platforms -custom: https://www.buymeacoffee.com/frankie567 +github: frankie567 From 02df6e9506ca1081177def3b3da27c740401bffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Mon, 18 Jul 2022 11:06:23 +0200 Subject: [PATCH 05/31] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b41109..42168c4 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ [![PyPI version](https://badge.fury.io/py/fastapi-users-db-beanie.svg)](https://badge.fury.io/py/fastapi-users-db-beanie) [![Downloads](https://pepy.tech/badge/fastapi-users-db-beanie)](https://pepy.tech/project/fastapi-users-db-beanie)

- +

--- From c061aac996ecc74e367e8285cc5221766bcff752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Mon, 18 Jul 2022 18:01:25 +0200 Subject: [PATCH 06/31] Fix md-buttons URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 42168c4..0e68642 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ [![PyPI version](https://badge.fury.io/py/fastapi-users-db-beanie.svg)](https://badge.fury.io/py/fastapi-users-db-beanie) [![Downloads](https://pepy.tech/badge/fastapi-users-db-beanie)](https://pepy.tech/project/fastapi-users-db-beanie)

- +

--- From 4146588b64542e4adae8651adcbc644d94d4ba1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Thu, 11 Aug 2022 17:25:09 +0200 Subject: [PATCH 07/31] Fix BMAC button --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e68642..61448d0 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ [![PyPI version](https://badge.fury.io/py/fastapi-users-db-beanie.svg)](https://badge.fury.io/py/fastapi-users-db-beanie) [![Downloads](https://pepy.tech/badge/fastapi-users-db-beanie)](https://pepy.tech/project/fastapi-users-db-beanie)

- +

--- From d47b1ba830c66b73d8b2ebf6067f7c43b05533fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Oct 2022 08:37:07 +0200 Subject: [PATCH 08/31] Update beanie requirement from <1.12,>=1.11.0 to >=1.11.0,<1.14 (#5) Updates the requirements on [beanie](https://github.com/roman-right/beanie) to permit the latest version. - [Release notes](https://github.com/roman-right/beanie/releases) - [Changelog](https://github.com/roman-right/beanie/blob/main/docs/changelog.md) - [Commits](https://github.com/roman-right/beanie/compare/1.11.0...1.13.0) --- updated-dependencies: - dependency-name: beanie dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7bb14ec..c2d6c5a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ classifiers = [ requires-python = ">=3.7" dependencies = [ "fastapi-users >= 10.0.1", - "beanie >=1.11.0,<1.12", + "beanie >=1.11.0,<1.14", ] [project.optional-dependencies] From 02edad51dc80e59fcfae46bc55de24f41e446d37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Tue, 25 Oct 2022 08:49:36 +0200 Subject: [PATCH 09/31] Move to Hatch for package management --- .github/workflows/build.yml | 53 ++++++++++++++++-------- Makefile | 27 ------------- README.md | 32 ++------------- pyproject.toml | 80 +++++++++++++++++++++++++------------ 4 files changed, 94 insertions(+), 98 deletions(-) delete mode 100644 Makefile diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c2f1df3..911811e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,27 +10,38 @@ jobs: matrix: python_version: [3.7, 3.8, 3.9, '3.10'] + services: + mongo: + image: mongo + ports: + - 27017:27017 + steps: - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python_version }} - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flit - flit install --deps develop - - name: Test with pytest - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + pip install hatch + hatch env create + - name: Lint and typecheck + run: | + hatch run lint-check + - name: Test run: | - pytest --cov=fastapi_users_db_beanie/ - codecov + hatch run test-cov-xml + - uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + fail_ci_if_error: true + verbose: true - name: Build and install it on system host run: | - flit build - flit install --python $(which python) + hatch build + pip install dist/fastapi_users-*.whl python test_build.py release: @@ -41,17 +52,25 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: 3.7 - name: Install dependencies + shell: bash run: | python -m pip install --upgrade pip - pip install flit - flit install --deps develop - - name: Release on PyPI + pip install hatch + - name: Build and publish on PyPI env: - FLIT_USERNAME: ${{ secrets.FLIT_USERNAME }} - FLIT_PASSWORD: ${{ secrets.FLIT_PASSWORD }} + HATCH_INDEX_USER: ${{ secrets.HATCH_INDEX_USER }} + HATCH_INDEX_AUTH: ${{ secrets.HATCH_INDEX_AUTH }} run: | - flit publish + hatch build + hatch publish + - name: Create release + uses: ncipollo/release-action@v1 + with: + draft: true + body: ${{ github.event.head_commit.message }} + artifacts: dist/*.whl,dist/*.tar.gz + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Makefile b/Makefile deleted file mode 100644 index 72ddef6..0000000 --- a/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -MONGODB_CONTAINER_NAME := fastapi-users-db-beanie-test-mongo - -install: - python -m pip install --upgrade pip - pip install flit - flit install --deps develop - -isort: - isort ./fastapi_users_db_beanie ./tests - -format: isort - black . - -test: - docker stop $(MONGODB_CONTAINER_NAME) || true - docker run -d --rm --name $(MONGODB_CONTAINER_NAME) -p 27017:27017 mongo:4.4 - pytest --cov=fastapi_users_db_beanie/ --cov-report=term-missing --cov-fail-under=100 - docker stop $(MONGODB_CONTAINER_NAME) - -bumpversion-major: - bumpversion major - -bumpversion-minor: - bumpversion minor - -bumpversion-patch: - bumpversion patch diff --git a/README.md b/README.md index 61448d0..cf9ece6 100644 --- a/README.md +++ b/README.md @@ -32,40 +32,14 @@ Add quickly a registration and authentication system to your [FastAPI](https://f ### Setup environment -You should create a virtual environment and activate it: - -```bash -python -m venv venv/ -``` - -```bash -source venv/bin/activate -``` - -And then install the development dependencies: - -```bash -make install -``` +We use [Hatch](https://hatch.pypa.io/latest/install/) to manage the development environment and production build. Ensure it's installed on your system. ### Run unit tests You can run all the tests with: ```bash -make test -``` - -Alternatively, you can run `pytest` yourself: - -```bash -pytest -``` - -There are quite a few unit tests, so you might run into ulimit issues where there are too many open file descriptors. You may be able to set a new, higher limit temporarily with: - -```bash -ulimit -n 2048 +hatch run test ``` ### Format the code @@ -73,7 +47,7 @@ ulimit -n 2048 Execute the following command to apply `isort` and `black` formatting: ```bash -make format +hatch run lint ``` ## License diff --git a/pyproject.toml b/pyproject.toml index c2d6c5a..a4135ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,12 +5,61 @@ profile = "black" asyncio_mode = "auto" addopts = "--ignore=test_build.py" -[build-system] -requires = ["flit_core >=3.2,<4"] -build-backend = "flit_core.buildapi" +[tool.hatch] + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.version] +source = "regex_commit" +commit_extra_args = ["-e"] +path = "fastapi_users_db_beanie/__init__.py" + +[tool.hatch.envs.default] +dependencies = [ + "flake8", + "pytest", + "requests", + "isort", + "pytest-asyncio", + "flake8-docstrings", + "black", + "mypy", + "codecov", + "pytest-cov", + "pytest-mock", + "asynctest", + "flit", + "bumpversion", + "httpx", + "asgi_lifespan", +] + +[tool.hatch.envs.default.scripts] +test = [ + "docker stop fastapi-users-db-beanie-test-mongo || true", + "docker run -d --rm --name fastapi-users-db-beanie-test-mongo -p 27017:27017 mongo:4.4", + "pytest --cov=fastapi_users_db_beanie/ --cov-report=term-missing --cov-fail-under=100", + "docker stop fastapi-users-db-beanie-test-mongo", +] +test-cov-xml = "pytest --cov=fastapi_users_db_beanie/ --cov-report=xml --cov-fail-under=100" +lint = [ + "isort ./fastapi_users_db_beanie ./tests", + "black . ", + "mypy fastapi_users_db_beanie/", +] +lint-check = [ + "isort --check-only ./fastapi_users_db_beanie ./tests", + "black --check .", + "mypy fastapi_users_db_beanie/", +] -[tool.flit.module] -name = "fastapi_users_db_beanie" +[tool.hatch.build.targets.sdist] +support-legacy = true # Create setup.py + +[build-system] +requires = ["hatchling", "hatch-regex-commit"] +build-backend = "hatchling.build" [project] name = "fastapi-users-db-beanie" @@ -40,25 +89,6 @@ dependencies = [ "beanie >=1.11.0,<1.14", ] -[project.optional-dependencies] -dev = [ - "flake8", - "pytest", - "requests", - "isort", - "pytest-asyncio", - "flake8-docstrings", - "black", - "mypy", - "codecov", - "pytest-cov", - "pytest-mock", - "asynctest", - "flit", - "bumpversion", - "httpx", - "asgi_lifespan", -] - [project.urls] Documentation = "https://fastapi-users.github.io/fastapi-users" +Source = "https://github.com/fastapi-users/fastapi-users-db-beanie" From a9ec052f1bf76d32df80c521b39aed091d6cbe67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Tue, 25 Oct 2022 08:51:17 +0200 Subject: [PATCH 10/31] Fix CI --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 911811e..d700ff4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ jobs: - name: Build and install it on system host run: | hatch build - pip install dist/fastapi_users-*.whl + pip install dist/fastapi_users_db_beanie-*.whl python test_build.py release: From 217b1d3fe78dacc0452216afa0dbd13e2daa58a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Tue, 25 Oct 2022 08:53:27 +0200 Subject: [PATCH 11/31] =?UTF-8?q?Bump=20version=201.1.1=20=E2=86=92=201.1.?= =?UTF-8?q?2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improvements ------------ * Bump dependencies: * `beanie >=1.11.0,<1.14` --- fastapi_users_db_beanie/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index e71511d..f6a70ab 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -10,7 +10,7 @@ from pymongo import IndexModel from pymongo.collation import Collation -__version__ = "1.1.1" +__version__ = "1.1.2" class BeanieBaseUser(Generic[ID], Document): From 49f99f76ab6d2872de39b5c5bab7baa288a8506e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Tue, 25 Oct 2022 08:54:55 +0200 Subject: [PATCH 12/31] Remove useless dev dependencies --- pyproject.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a4135ca..315f0a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,8 +29,6 @@ dependencies = [ "pytest-cov", "pytest-mock", "asynctest", - "flit", - "bumpversion", "httpx", "asgi_lifespan", ] From a87ba4060f3cb08cab9bd15795717ec8436e162a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Mon, 16 Jan 2023 10:29:17 +0100 Subject: [PATCH 13/31] Bump Beanie --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 315f0a9..fec3259 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -84,7 +84,7 @@ classifiers = [ requires-python = ">=3.7" dependencies = [ "fastapi-users >= 10.0.1", - "beanie >=1.11.0,<1.14", + "beanie >=1.11.0,<1.17", ] [project.urls] From 15d98b81aba923958309bd19ae7e6600ef8a2eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Mon, 16 Jan 2023 10:31:10 +0100 Subject: [PATCH 14/31] Use Ruff linter --- pyproject.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fec3259..311ed44 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,9 @@ profile = "black" asyncio_mode = "auto" addopts = "--ignore=test_build.py" +[tool.ruff] +extend-select = ["I"] + [tool.hatch] [tool.hatch.metadata] @@ -17,12 +20,8 @@ path = "fastapi_users_db_beanie/__init__.py" [tool.hatch.envs.default] dependencies = [ - "flake8", "pytest", - "requests", - "isort", "pytest-asyncio", - "flake8-docstrings", "black", "mypy", "codecov", @@ -31,6 +30,7 @@ dependencies = [ "asynctest", "httpx", "asgi_lifespan", + "ruff", ] [tool.hatch.envs.default.scripts] @@ -42,13 +42,13 @@ test = [ ] test-cov-xml = "pytest --cov=fastapi_users_db_beanie/ --cov-report=xml --cov-fail-under=100" lint = [ - "isort ./fastapi_users_db_beanie ./tests", "black . ", + "ruff --fix .", "mypy fastapi_users_db_beanie/", ] lint-check = [ - "isort --check-only ./fastapi_users_db_beanie ./tests", "black --check .", + "ruff .", "mypy fastapi_users_db_beanie/", ] From 4600ae2aa1f48953707432671121035609c28dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Mon, 16 Jan 2023 10:31:52 +0100 Subject: [PATCH 15/31] Enable Pytho 3.11 in test matrix --- .github/workflows/build.yml | 2 +- pyproject.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d700ff4..a69af08 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python_version: [3.7, 3.8, 3.9, '3.10'] + python_version: [3.7, 3.8, 3.9, '3.10', '3.11'] services: mongo: diff --git a/pyproject.toml b/pyproject.toml index 311ed44..090c0eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,6 +78,7 @@ classifiers = [ "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3 :: Only", "Topic :: Internet :: WWW/HTTP :: Session", ] From 8577fd190f1e96ccfb4ce479cf19b4fbee252ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Mon, 16 Jan 2023 10:34:01 +0100 Subject: [PATCH 16/31] =?UTF-8?q?Bump=20version=201.1.2=20=E2=86=92=201.1.?= =?UTF-8?q?3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improvements ------------ * Enable Python 3.11 support * Bump dependencies: * `beanie >=1.11.0,<1.17` --- fastapi_users_db_beanie/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index f6a70ab..cde1505 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -10,7 +10,7 @@ from pymongo import IndexModel from pymongo.collation import Collation -__version__ = "1.1.2" +__version__ = "1.1.3" class BeanieBaseUser(Generic[ID], Document): From 33cb9ed3fd16764c2dd1e00d5900d9174000dcad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Mon, 16 Jan 2023 11:20:51 +0100 Subject: [PATCH 17/31] Remove useless tooling --- pyproject.toml | 3 --- setup.cfg | 14 -------------- 2 files changed, 17 deletions(-) delete mode 100644 setup.cfg diff --git a/pyproject.toml b/pyproject.toml index 090c0eb..8c27124 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,3 @@ -[tool.isort] -profile = "black" - [tool.pytest.ini_options] asyncio_mode = "auto" addopts = "--ignore=test_build.py" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index b26df6a..0000000 --- a/setup.cfg +++ /dev/null @@ -1,14 +0,0 @@ -[bumpversion] -current_version = 1.1.1 -commit = True -tag = True - -[bumpversion:file:fastapi_users_db_beanie/__init__.py] -search = __version__ = "{current_version}" -replace = __version__ = "{new_version}" - -[flake8] -exclude = docs -max-line-length = 88 -docstring-convention = numpy -ignore = D1 From 259f00c6b3bcd1b0b379cfb4aa13d11351df4c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Tue, 24 Jan 2023 11:22:36 +0100 Subject: [PATCH 18/31] Fix #9: bump beanie >=1.11.0,<2.0.0 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8c27124..ac6d254 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,7 +82,7 @@ classifiers = [ requires-python = ">=3.7" dependencies = [ "fastapi-users >= 10.0.1", - "beanie >=1.11.0,<1.17", + "beanie >=1.11.0,<2.0.0", ] [project.urls] From d380a5b8932b1f3bddb990e023236875d6655cb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Tue, 24 Jan 2023 11:32:00 +0100 Subject: [PATCH 19/31] =?UTF-8?q?Bump=20version=201.1.3=20=E2=86=92=201.1.?= =?UTF-8?q?4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improvements ------------ * Bump dependencies * `beanie >=1.11.0,<2.0.0` --- fastapi_users_db_beanie/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index cde1505..6b4c22f 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -10,7 +10,7 @@ from pymongo import IndexModel from pymongo.collation import Collation -__version__ = "1.1.3" +__version__ = "1.1.4" class BeanieBaseUser(Generic[ID], Document): From d0c08cf0f47960e2f5b6e3905bb00c359ecda714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Tue, 14 Feb 2023 17:10:31 +0100 Subject: [PATCH 20/31] Update md-buttons URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cf9ece6..afa3c47 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ [![PyPI version](https://badge.fury.io/py/fastapi-users-db-beanie.svg)](https://badge.fury.io/py/fastapi-users-db-beanie) [![Downloads](https://pepy.tech/badge/fastapi-users-db-beanie)](https://pepy.tech/project/fastapi-users-db-beanie)

- +

--- From f835660fda6f111455bff3a4a31a497fe7ccdbd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Fri, 14 Apr 2023 13:55:58 +0200 Subject: [PATCH 21/31] Remove useless codecov dependency --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ac6d254..c034042 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,6 @@ dependencies = [ "pytest-asyncio", "black", "mypy", - "codecov", "pytest-cov", "pytest-mock", "asynctest", From 206a1e545ff7a049785c4096691e4e843decdcc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Fri, 14 Apr 2023 14:10:01 +0200 Subject: [PATCH 22/31] Fix incompatibility with Beanie 0.18 --- fastapi_users_db_beanie/__init__.py | 12 ++++++++---- fastapi_users_db_beanie/access_token.py | 6 ++++-- tests/conftest.py | 12 ++---------- tests/test_access_token.py | 7 +++++-- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index 6b4c22f..8bc8b01 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -89,13 +89,15 @@ async def get_by_oauth_account( async def create(self, create_dict: Dict[str, Any]) -> UP_BEANIE: """Create a user.""" user = self.user_model(**create_dict) - return await user.insert() + await user.create() + return user async def update(self, user: UP_BEANIE, update_dict: Dict[str, Any]) -> UP_BEANIE: """Update a user.""" for key, value in update_dict.items(): setattr(user, key, value) - return await user.save() + await user.save() + return user async def delete(self, user: UP_BEANIE) -> None: """Delete a user.""" @@ -111,7 +113,8 @@ async def add_oauth_account( oauth_account = self.oauth_account_model(**create_dict) user.oauth_accounts.append(oauth_account) # type: ignore - return await user.save() + await user.save() + return user async def update_oauth_account( self, user: UP_BEANIE, oauth_account: OAP, update_dict: Dict[str, Any] @@ -128,7 +131,8 @@ async def update_oauth_account( for key, value in update_dict.items(): setattr(user.oauth_accounts[i], key, value) # type: ignore - return await user.save() + await user.save() + return user class ObjectIDIDMixin: diff --git a/fastapi_users_db_beanie/access_token.py b/fastapi_users_db_beanie/access_token.py index 8719484..01f7b8e 100644 --- a/fastapi_users_db_beanie/access_token.py +++ b/fastapi_users_db_beanie/access_token.py @@ -40,14 +40,16 @@ async def get_by_token( async def create(self, create_dict: Dict[str, Any]) -> AP_BEANIE: access_token = self.access_token_model(**create_dict) - return await access_token.save() + await access_token.create() + return access_token async def update( self, access_token: AP_BEANIE, update_dict: Dict[str, Any] ) -> AP_BEANIE: for key, value in update_dict.items(): setattr(access_token, key, value) - return await access_token.save() + await access_token.save() + return access_token async def delete(self, access_token: AP_BEANIE) -> None: await access_token.delete() diff --git a/tests/conftest.py b/tests/conftest.py index 37435ca..4ab3680 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,17 +6,9 @@ @pytest.fixture(scope="session") def event_loop(): - """ - Force the pytest-asyncio loop to be the main one. - If there is no running event loop, create one and - set as the current one. - """ - try: - loop = asyncio.get_running_loop() - except RuntimeError: - loop = asyncio.new_event_loop() - asyncio.set_event_loop(loop) + loop = asyncio.get_event_loop() yield loop + loop.close() @pytest.fixture diff --git a/tests/test_access_token.py b/tests/test_access_token.py index 6ec4dad..76b36fd 100644 --- a/tests/test_access_token.py +++ b/tests/test_access_token.py @@ -63,11 +63,14 @@ async def test_queries( assert access_token.user_id == user_id # Update - update_dict = {"created_at": datetime.now(timezone.utc)} + updated_created_at = datetime.now(timezone.utc) + update_dict = {"created_at": updated_created_at} updated_access_token = await beanie_access_token_db.update( access_token, update_dict ) - assert updated_access_token.created_at == update_dict["created_at"] + assert updated_access_token.created_at == update_dict["created_at"].replace( + microsecond=int(updated_created_at.microsecond / 1000) * 1000, tzinfo=None + ) # Get by token access_token_by_token = await beanie_access_token_db.get_by_token( From fab7f9377c0bc95cb40176f0946c6358b6be3699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Fri, 14 Apr 2023 15:32:30 +0200 Subject: [PATCH 23/31] Make BeanieBaseUser and BeanieBaseAccessToken pure mixins to avoid duplicate collections --- fastapi_users_db_beanie/__init__.py | 16 ++++++++++------ fastapi_users_db_beanie/access_token.py | 24 +++++++++++++++++------- tests/test_access_token.py | 4 ++-- tests/test_fastapi_users_db_beanie.py | 16 +++++++--------- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index 8bc8b01..151884d 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -1,5 +1,5 @@ """FastAPI Users database adapter for Beanie.""" -from typing import TYPE_CHECKING, Any, Dict, Generic, Optional, Type, TypeVar +from typing import Any, Dict, Generic, Optional, Type, TypeVar import bson.errors from beanie import Document, PydanticObjectId @@ -13,9 +13,7 @@ __version__ = "1.1.4" -class BeanieBaseUser(Generic[ID], Document): - if TYPE_CHECKING: - id: ID # type: ignore # pragma: no cover +class BeanieBaseUser(BaseModel): email: str hashed_password: str is_active: bool = True @@ -32,7 +30,11 @@ class Settings: ] -UP_BEANIE = TypeVar("UP_BEANIE", bound=BeanieBaseUser) +class BeanieBaseUserDocument(BeanieBaseUser, Document): # type: ignore + pass + + +UP_BEANIE = TypeVar("UP_BEANIE", bound=BeanieBaseUserDocument) class BaseOAuthAccount(BaseModel): @@ -45,7 +47,9 @@ class BaseOAuthAccount(BaseModel): refresh_token: Optional[str] = None -class BeanieUserDatabase(Generic[UP_BEANIE, ID], BaseUserDatabase[UP_BEANIE, ID]): +class BeanieUserDatabase( + Generic[UP_BEANIE], BaseUserDatabase[UP_BEANIE, PydanticObjectId] +): """ Database adapter for Beanie. diff --git a/fastapi_users_db_beanie/access_token.py b/fastapi_users_db_beanie/access_token.py index 01f7b8e..497257d 100644 --- a/fastapi_users_db_beanie/access_token.py +++ b/fastapi_users_db_beanie/access_token.py @@ -1,23 +1,33 @@ from datetime import datetime, timezone -from typing import Any, Dict, Generic, Optional, Type, TypeVar +from typing import ( + Any, + Dict, + Generic, + Optional, + Type, + TypeVar, +) -from beanie import Document +from beanie import Document, PydanticObjectId from fastapi_users.authentication.strategy.db import AccessTokenDatabase -from fastapi_users.models import ID -from pydantic import Field +from pydantic import BaseModel, Field from pymongo import IndexModel -class BeanieBaseAccessToken(Generic[ID], Document): +class BeanieBaseAccessToken(BaseModel): token: str - user_id: ID + user_id: PydanticObjectId created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc)) class Settings: indexes = [IndexModel("token", unique=True)] -AP_BEANIE = TypeVar("AP_BEANIE", bound=BeanieBaseAccessToken) +class BeanieBaseAccessTokenDocument(BeanieBaseAccessToken, Document): # type: ignore + pass + + +AP_BEANIE = TypeVar("AP_BEANIE", bound=BeanieBaseAccessTokenDocument) class BeanieAccessTokenDatabase(Generic[AP_BEANIE], AccessTokenDatabase[AP_BEANIE]): diff --git a/tests/test_access_token.py b/tests/test_access_token.py index 76b36fd..183fff7 100644 --- a/tests/test_access_token.py +++ b/tests/test_access_token.py @@ -3,7 +3,7 @@ import pymongo.errors import pytest -from beanie import PydanticObjectId, init_beanie +from beanie import Document, PydanticObjectId, init_beanie from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase from fastapi_users_db_beanie.access_token import ( @@ -12,7 +12,7 @@ ) -class AccessToken(BeanieBaseAccessToken[PydanticObjectId]): +class AccessToken(BeanieBaseAccessToken, Document): pass diff --git a/tests/test_fastapi_users_db_beanie.py b/tests/test_fastapi_users_db_beanie.py index a91cbb8..bbe1e24 100644 --- a/tests/test_fastapi_users_db_beanie.py +++ b/tests/test_fastapi_users_db_beanie.py @@ -2,7 +2,7 @@ import pymongo.errors import pytest -from beanie import PydanticObjectId, init_beanie +from beanie import Document, PydanticObjectId, init_beanie from fastapi_users import InvalidID from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase from pydantic import Field @@ -15,7 +15,7 @@ ) -class User(BeanieBaseUser[PydanticObjectId]): +class User(Document, BeanieBaseUser): first_name: Optional[str] = None @@ -70,7 +70,7 @@ async def beanie_user_db_oauth( @pytest.mark.asyncio async def test_queries( - beanie_user_db: BeanieUserDatabase[User, PydanticObjectId], + beanie_user_db: BeanieUserDatabase[User], oauth_account1: Dict[str, Any], ): user_create = { @@ -140,7 +140,7 @@ async def test_queries( ], ) async def test_email_query( - beanie_user_db: BeanieUserDatabase[User, PydanticObjectId], + beanie_user_db: BeanieUserDatabase[User], email: str, query: str, found: bool, @@ -161,9 +161,7 @@ async def test_email_query( @pytest.mark.asyncio -async def test_insert_existing_email( - beanie_user_db: BeanieUserDatabase[User, PydanticObjectId] -): +async def test_insert_existing_email(beanie_user_db: BeanieUserDatabase[User]): user_create = { "email": "lancelot@camelot.bt", "hashed_password": "guinevere", @@ -176,7 +174,7 @@ async def test_insert_existing_email( @pytest.mark.asyncio async def test_queries_custom_fields( - beanie_user_db: BeanieUserDatabase[User, PydanticObjectId], + beanie_user_db: BeanieUserDatabase[User], ): """It should output custom fields in query result.""" user_create = { @@ -195,7 +193,7 @@ async def test_queries_custom_fields( @pytest.mark.asyncio async def test_queries_oauth( - beanie_user_db_oauth: BeanieUserDatabase[UserOAuth, PydanticObjectId], + beanie_user_db_oauth: BeanieUserDatabase[UserOAuth], oauth_account1: Dict[str, Any], oauth_account2: Dict[str, Any], ): From 5328ef20428d6bfd3dbb1b8feafaf573cd72612d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Fri, 14 Apr 2023 15:35:24 +0200 Subject: [PATCH 24/31] =?UTF-8?q?Bump=20version=201.1.4=20=E2=86=92=202.0.?= =?UTF-8?q?0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Breaking changes ---------------- * `BeanieBaseUser` and `BeanieBaseAccessToken` are now pure mixins and doesn't inherit `Document` by default. This change was made to avoid Beanie from creating duplicate collections in your database. You now need to inherit from `Document` yourself when declaring your model. * `BeanieBaseUser` now only supports `PydanticObjectId` as ID type. **BEFORE** ```py class User(BeanieBaseUser[PydanticObjectId]): pass ``` **AFTER** ```py class User(BeanieBaseUser, Document): pass ``` **BEFORE** ```py class AccessToken(BeanieBaseAccessToken[PydanticObjectId]): pass ``` **AFTER** ```py class AccessToken(BeanieBaseAccessToken, Document): pass ``` Bug fixes --------- * Fix support for Beanie >= 0.18. --- fastapi_users_db_beanie/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index 151884d..77a6599 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -10,7 +10,7 @@ from pymongo import IndexModel from pymongo.collation import Collation -__version__ = "1.1.4" +__version__ = "2.0.0" class BeanieBaseUser(BaseModel): From 9c1bbc17558c2f1e52f1501342f07d485f5b774c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Tue, 27 Jun 2023 15:35:06 +0200 Subject: [PATCH 25/31] Drop Python 3.7 support --- .github/workflows/build.yml | 4 ++-- pyproject.toml | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a69af08..2c1679f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python_version: [3.7, 3.8, 3.9, '3.10', '3.11'] + python_version: [3.8, 3.9, '3.10', '3.11'] services: mongo: @@ -54,7 +54,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.7 + python-version: 3.8 - name: Install dependencies shell: bash run: | diff --git a/pyproject.toml b/pyproject.toml index c034042..40057f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,7 +70,6 @@ classifiers = [ "Framework :: FastAPI", "Framework :: AsyncIO", "Intended Audience :: Developers", - "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", @@ -78,7 +77,7 @@ classifiers = [ "Programming Language :: Python :: 3 :: Only", "Topic :: Internet :: WWW/HTTP :: Session", ] -requires-python = ">=3.7" +requires-python = ">=3.8" dependencies = [ "fastapi-users >= 10.0.1", "beanie >=1.11.0,<2.0.0", From eedd1039cd8d3aece0f49fa1a90d9649ca80d1ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Tue, 27 Jun 2023 15:36:41 +0200 Subject: [PATCH 26/31] =?UTF-8?q?Bump=20version=202.0.0=20=E2=86=92=203.0.?= =?UTF-8?q?0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Breaking changes ---------------- * Drop Python 3.7 support --- fastapi_users_db_beanie/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index 77a6599..6a73f7f 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -10,7 +10,7 @@ from pymongo import IndexModel from pymongo.collation import Collation -__version__ = "2.0.0" +__version__ = "3.0.0" class BeanieBaseUser(BaseModel): From c996a5c73ab7731270ee6318cd6c67fa439324bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Sat, 4 Jan 2025 13:52:00 +0100 Subject: [PATCH 27/31] Drop Python 3.8 support and upgrade tooling --- .github/workflows/build.yml | 4 ++-- .gitignore | 3 --- .vscode/settings.json | 21 +++++++++++++++++++++ fastapi_users_db_beanie/__init__.py | 22 +++++++++++++--------- fastapi_users_db_beanie/access_token.py | 10 ++++------ pyproject.toml | 20 ++++++++++++-------- tests/conftest.py | 14 +++----------- tests/test_access_token.py | 7 ++++--- tests/test_fastapi_users_db_beanie.py | 18 ++++++++++-------- 9 files changed, 69 insertions(+), 50 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2c1679f..10dd103 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python_version: [3.8, 3.9, '3.10', '3.11'] + python_version: [3.9, '3.10', '3.11', '3.12', '3.13'] services: mongo: @@ -54,7 +54,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: 3.9 - name: Install dependencies shell: bash run: | diff --git a/.gitignore b/.gitignore index b949f48..434348e 100644 --- a/.gitignore +++ b/.gitignore @@ -104,9 +104,6 @@ ENV/ # mypy .mypy_cache/ -# .vscode -.vscode/ - # OS files .DS_Store diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..57715ca --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,21 @@ +{ + "python.analysis.typeCheckingMode": "basic", + "python.analysis.autoImportCompletions": true, + "python.terminal.activateEnvironment": true, + "python.terminal.activateEnvInCurrentTerminal": true, + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "editor.rulers": [88], + "python.defaultInterpreterPath": "${workspaceFolder}/.hatch/fastapi-users-db-beanie/bin/python", + "python.testing.pytestPath": "${workspaceFolder}/.hatch/fastapi-users-db-beanie/bin/pytest", + "python.testing.cwd": "${workspaceFolder}", + "python.testing.pytestArgs": ["--no-cov"], + "[python]": { + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + "source.organizeImports": "explicit" + }, + "editor.defaultFormatter": "charliermarsh.ruff" + } + } diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index 6a73f7f..a65674f 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -1,5 +1,6 @@ """FastAPI Users database adapter for Beanie.""" -from typing import Any, Dict, Generic, Optional, Type, TypeVar + +from typing import Any, Generic, Optional, TypeVar import bson.errors from beanie import Document, PydanticObjectId @@ -23,9 +24,12 @@ class BeanieBaseUser(BaseModel): class Settings: email_collation = Collation("en", strength=2) indexes = [ - IndexModel("email", unique=True), + IndexModel("email"), IndexModel( - "email", name="case_insensitive_email_index", collation=email_collation + "email", + name="case_insensitive_email_index", + collation=email_collation, + unique=True, ), ] @@ -59,8 +63,8 @@ class BeanieUserDatabase( def __init__( self, - user_model: Type[UP_BEANIE], - oauth_account_model: Optional[Type[BaseOAuthAccount]] = None, + user_model: type[UP_BEANIE], + oauth_account_model: Optional[type[BaseOAuthAccount]] = None, ): self.user_model = user_model self.oauth_account_model = oauth_account_model @@ -90,13 +94,13 @@ async def get_by_oauth_account( } ) - async def create(self, create_dict: Dict[str, Any]) -> UP_BEANIE: + async def create(self, create_dict: dict[str, Any]) -> UP_BEANIE: """Create a user.""" user = self.user_model(**create_dict) await user.create() return user - async def update(self, user: UP_BEANIE, update_dict: Dict[str, Any]) -> UP_BEANIE: + async def update(self, user: UP_BEANIE, update_dict: dict[str, Any]) -> UP_BEANIE: """Update a user.""" for key, value in update_dict.items(): setattr(user, key, value) @@ -108,7 +112,7 @@ async def delete(self, user: UP_BEANIE) -> None: await user.delete() async def add_oauth_account( - self, user: UP_BEANIE, create_dict: Dict[str, Any] + self, user: UP_BEANIE, create_dict: dict[str, Any] ) -> UP_BEANIE: """Create an OAuth account and add it to the user.""" if self.oauth_account_model is None: @@ -121,7 +125,7 @@ async def add_oauth_account( return user async def update_oauth_account( - self, user: UP_BEANIE, oauth_account: OAP, update_dict: Dict[str, Any] + self, user: UP_BEANIE, oauth_account: OAP, update_dict: dict[str, Any] ) -> UP_BEANIE: """Update an OAuth account on a user.""" if self.oauth_account_model is None: diff --git a/fastapi_users_db_beanie/access_token.py b/fastapi_users_db_beanie/access_token.py index 497257d..10d9f54 100644 --- a/fastapi_users_db_beanie/access_token.py +++ b/fastapi_users_db_beanie/access_token.py @@ -1,10 +1,8 @@ from datetime import datetime, timezone from typing import ( Any, - Dict, Generic, Optional, - Type, TypeVar, ) @@ -37,24 +35,24 @@ class BeanieAccessTokenDatabase(Generic[AP_BEANIE], AccessTokenDatabase[AP_BEANI :param access_token_model: Beanie access token model. """ - def __init__(self, access_token_model: Type[AP_BEANIE]): + def __init__(self, access_token_model: type[AP_BEANIE]): self.access_token_model = access_token_model async def get_by_token( self, token: str, max_age: Optional[datetime] = None ) -> Optional[AP_BEANIE]: - query: Dict[str, Any] = {"token": token} + query: dict[str, Any] = {"token": token} if max_age is not None: query["created_at"] = {"$gte": max_age} return await self.access_token_model.find_one(query) - async def create(self, create_dict: Dict[str, Any]) -> AP_BEANIE: + async def create(self, create_dict: dict[str, Any]) -> AP_BEANIE: access_token = self.access_token_model(**create_dict) await access_token.create() return access_token async def update( - self, access_token: AP_BEANIE, update_dict: Dict[str, Any] + self, access_token: AP_BEANIE, update_dict: dict[str, Any] ) -> AP_BEANIE: for key, value in update_dict.items(): setattr(access_token, key, value) diff --git a/pyproject.toml b/pyproject.toml index 40057f7..1f66470 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,13 @@ [tool.pytest.ini_options] -asyncio_mode = "auto" +asyncio_mode = "strict" +asyncio_default_fixture_loop_scope = "function" addopts = "--ignore=test_build.py" [tool.ruff] -extend-select = ["I"] +target-version = "py39" + +[tool.ruff.lint] +extend-select = ["I", "UP"] [tool.hatch] @@ -16,6 +20,7 @@ commit_extra_args = ["-e"] path = "fastapi_users_db_beanie/__init__.py" [tool.hatch.envs.default] +installer = "uv" dependencies = [ "pytest", "pytest-asyncio", @@ -38,13 +43,13 @@ test = [ ] test-cov-xml = "pytest --cov=fastapi_users_db_beanie/ --cov-report=xml --cov-fail-under=100" lint = [ - "black . ", - "ruff --fix .", + "ruff format . ", + "ruff check --fix .", "mypy fastapi_users_db_beanie/", ] lint-check = [ - "black --check .", - "ruff .", + "ruff format --check .", + "ruff check .", "mypy fastapi_users_db_beanie/", ] @@ -70,14 +75,13 @@ classifiers = [ "Framework :: FastAPI", "Framework :: AsyncIO", "Intended Audience :: Developers", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3 :: Only", "Topic :: Internet :: WWW/HTTP :: Session", ] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = [ "fastapi-users >= 10.0.1", "beanie >=1.11.0,<2.0.0", diff --git a/tests/conftest.py b/tests/conftest.py index 4ab3680..ff46849 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,18 +1,10 @@ -import asyncio -from typing import Any, Dict +from typing import Any import pytest -@pytest.fixture(scope="session") -def event_loop(): - loop = asyncio.get_event_loop() - yield loop - loop.close() - - @pytest.fixture -def oauth_account1() -> Dict[str, Any]: +def oauth_account1() -> dict[str, Any]: return { "oauth_name": "service1", "access_token": "TOKEN", @@ -23,7 +15,7 @@ def oauth_account1() -> Dict[str, Any]: @pytest.fixture -def oauth_account2() -> Dict[str, Any]: +def oauth_account2() -> dict[str, Any]: return { "oauth_name": "service2", "access_token": "TOKEN", diff --git a/tests/test_access_token.py b/tests/test_access_token.py index 183fff7..bfb37b9 100644 --- a/tests/test_access_token.py +++ b/tests/test_access_token.py @@ -1,8 +1,9 @@ +from collections.abc import AsyncGenerator from datetime import datetime, timedelta, timezone -from typing import AsyncGenerator import pymongo.errors import pytest +import pytest_asyncio from beanie import Document, PydanticObjectId, init_beanie from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase @@ -16,7 +17,7 @@ class AccessToken(BeanieBaseAccessToken, Document): pass -@pytest.fixture(scope="module") +@pytest_asyncio.fixture async def mongodb_client(): client = AsyncIOMotorClient( "mongodb://localhost:27017", @@ -33,7 +34,7 @@ async def mongodb_client(): return -@pytest.fixture +@pytest_asyncio.fixture async def beanie_access_token_db( mongodb_client: AsyncIOMotorClient, ) -> AsyncGenerator[BeanieAccessTokenDatabase, None]: diff --git a/tests/test_fastapi_users_db_beanie.py b/tests/test_fastapi_users_db_beanie.py index bbe1e24..889c7fa 100644 --- a/tests/test_fastapi_users_db_beanie.py +++ b/tests/test_fastapi_users_db_beanie.py @@ -1,7 +1,9 @@ -from typing import Any, AsyncGenerator, Dict, List, Optional +from collections.abc import AsyncGenerator +from typing import Any, Optional import pymongo.errors import pytest +import pytest_asyncio from beanie import Document, PydanticObjectId, init_beanie from fastapi_users import InvalidID from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase @@ -24,10 +26,10 @@ class OAuthAccount(BaseOAuthAccount): class UserOAuth(User): - oauth_accounts: List[OAuthAccount] = Field(default_factory=list) + oauth_accounts: list[OAuthAccount] = Field(default_factory=list) -@pytest.fixture(scope="module") +@pytest_asyncio.fixture async def mongodb_client(): client = AsyncIOMotorClient( "mongodb://localhost:27017", @@ -44,7 +46,7 @@ async def mongodb_client(): return -@pytest.fixture +@pytest_asyncio.fixture async def beanie_user_db( mongodb_client: AsyncIOMotorClient, ) -> AsyncGenerator[BeanieUserDatabase, None]: @@ -56,7 +58,7 @@ async def beanie_user_db( await mongodb_client.drop_database("test_database") -@pytest.fixture +@pytest_asyncio.fixture async def beanie_user_db_oauth( mongodb_client: AsyncIOMotorClient, ) -> AsyncGenerator[BeanieUserDatabase, None]: @@ -71,7 +73,7 @@ async def beanie_user_db_oauth( @pytest.mark.asyncio async def test_queries( beanie_user_db: BeanieUserDatabase[User], - oauth_account1: Dict[str, Any], + oauth_account1: dict[str, Any], ): user_create = { "email": "lancelot@camelot.bt", @@ -194,8 +196,8 @@ async def test_queries_custom_fields( @pytest.mark.asyncio async def test_queries_oauth( beanie_user_db_oauth: BeanieUserDatabase[UserOAuth], - oauth_account1: Dict[str, Any], - oauth_account2: Dict[str, Any], + oauth_account1: dict[str, Any], + oauth_account2: dict[str, Any], ): user_create = { "email": "lancelot@camelot.bt", From 29b62913e2db1b442b12a1f3edf90d7c3b4f1811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Sat, 4 Jan 2025 13:58:41 +0100 Subject: [PATCH 28/31] Upgrade trove classifiers --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 1f66470..136e7f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -78,6 +78,8 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3 :: Only", "Topic :: Internet :: WWW/HTTP :: Session", ] From 26beac08e049c177e876a358a89744147d4ff8e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Sat, 4 Jan 2025 13:59:28 +0100 Subject: [PATCH 29/31] Use only one case insensitive index --- fastapi_users_db_beanie/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index a65674f..3d8304a 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -24,7 +24,6 @@ class BeanieBaseUser(BaseModel): class Settings: email_collation = Collation("en", strength=2) indexes = [ - IndexModel("email"), IndexModel( "email", name="case_insensitive_email_index", From 89d0cf680d6b5ca3642813d7954c5c395fcd395a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Sat, 4 Jan 2025 14:01:19 +0100 Subject: [PATCH 30/31] Upgrade GitHub Actions --- .github/workflows/build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 10dd103..779f35e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,9 +17,9 @@ jobs: - 27017:27017 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python_version }} - name: Install dependencies @@ -33,7 +33,7 @@ jobs: - name: Test run: | hatch run test-cov-xml - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true @@ -50,9 +50,9 @@ jobs: if: startsWith(github.ref, 'refs/tags/') steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.9 - name: Install dependencies From 7ab1bc5e08a12ab914d70f418b692642c9ad6a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Voron?= Date: Sat, 4 Jan 2025 14:02:41 +0100 Subject: [PATCH 31/31] =?UTF-8?q?Bump=20version=203.0.0=20=E2=86=92=204.0.?= =?UTF-8?q?0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Breaking changes ---------------- * Drop Python 3.8 support Bug fixes --------- * Fix unique index on email property --- fastapi_users_db_beanie/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi_users_db_beanie/__init__.py b/fastapi_users_db_beanie/__init__.py index 3d8304a..a59b590 100644 --- a/fastapi_users_db_beanie/__init__.py +++ b/fastapi_users_db_beanie/__init__.py @@ -11,7 +11,7 @@ from pymongo import IndexModel from pymongo.collation import Collation -__version__ = "3.0.0" +__version__ = "4.0.0" class BeanieBaseUser(BaseModel):