diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml index de5d4ae..b18c8f2 100644 --- a/.github/workflows/formatting.yml +++ b/.github/workflows/formatting.yml @@ -2,13 +2,25 @@ name: "Formatting" on: [push] jobs: + # The matrix "tool" values ("black", "isort") and the job's required-check names they produce + # ("black (3.11, ubuntu-latest, black)", "black (3.11, ubuntu-latest, isort)") are kept unchanged + # on purpose, even though both now run ruff under the hood - renaming them would leave the + # required status checks configured on the branch protection ruleset permanently pending. + # Renaming these labels for real requires updating that ruleset in the same change, which is an + # admin-level, org-visible change to what blocks merges and is intentionally out of scope here. black: + name: black (${{ matrix.python-version }}, ${{ matrix.os }}, ${{ matrix.tool }}) runs-on: ${{ matrix.os }} strategy: matrix: python-version: ["3.11"] os: [ubuntu-latest] tool: ["black", "isort"] + include: + - tool: "black" + command: "ruff format --check ." + - tool: "isort" + command: "ruff check --select I ." steps: - uses: actions/checkout@v7 - name: Install uv @@ -16,6 +28,6 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Install dependencies - run: uv sync --group formatting + run: uv sync --group linting - name: ${{ matrix.tool }} Code Formatter - run: uv run ${{ matrix.tool }} . --check + run: uv run ${{ matrix.command }} diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 5b7bc75..d3e7669 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -64,11 +64,9 @@ cd bo4e_schemas uv run bost -t v202401.0.1 -o ./ uv run bo4e-generator -i ./ -o ../src/borm/models -ot sql_model - - name: Run pylint + - name: Run ruff check run: | - uv run pylint src/borm --disable R0801 --ignore-paths 'src/borm/models' - uv run pylint src/borm/models --rcfile=./.pylintrc_autogen_code - uv run pylint tests --rcfile=tests/.pylintrc + uv run ruff check src/borm tests # coverage - name: Install Dependencies (coverage) diff --git a/.github/workflows/pythonlint.yml b/.github/workflows/pythonlint.yml index 31aaa8a..2d490a2 100644 --- a/.github/workflows/pythonlint.yml +++ b/.github/workflows/pythonlint.yml @@ -32,12 +32,10 @@ jobs: cd bo4e_schemas uv run bost -t v202401.0.1 -o ./ uv run bo4e-generator -i ./ -o ../src/borm/models -ot sql_model - - name: Run pylint + - name: Run ruff check if: matrix.linter-env == 'linting' run: | - uv run pylint src/borm --disable R0801 --ignore-paths 'src/borm/models' - uv run pylint src/borm/models --rcfile=./.pylintrc_autogen_code - uv run pylint tests --rcfile=tests/.pylintrc + uv run ruff check src/borm tests - name: Run mypy if: matrix.linter-env == 'type_check' run: | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4ca5e22..2f005b1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,22 +6,12 @@ repos: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - - repo: https://github.com/psf/black - rev: 25.1.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.16.0 hooks: - - id: black - language_version: python3 - - repo: https://github.com/pycqa/isort - rev: 5.13.2 - hooks: - - id: isort - name: isort (python) - - id: isort - name: isort (cython) - types: [cython] - - id: isort - name: isort (pyi) - types: [pyi] + - id: ruff-check + args: [--fix] + - id: ruff-format - repo: https://github.com/astral-sh/uv-pre-commit rev: 0.11.32 hooks: diff --git a/.pylintrc_autogen_code b/.pylintrc_autogen_code deleted file mode 100644 index fe97f24..0000000 --- a/.pylintrc_autogen_code +++ /dev/null @@ -1,11 +0,0 @@ -[pylint] -#run for the code generated files -#know things to be fixed: -disable = - R0801, # disable similar lines - C0114, # disable missing-module-docstring - C0115, # disable missing-class-docstring - W0611, # disable unused-import - C0301, # disable line-too-long ->lines in comments too long - C0302, # disable too-many-lines -> many-many relationship classes -[pylint."MESSAGES CONTROL"] diff --git a/README.md b/README.md index bc36d2c..38ea37c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![Unittests status badge](https://github.com/Hochfrequenz/bo4e-python-orm/workflows/tests/badge.svg) ![Coverage status badge](https://github.com/Hochfrequenz/bo4e-python-orm/workflows/Coverage/badge.svg) ![Linting status badge](https://github.com/Hochfrequenz/bo4e-python-orm/workflows/Linting/badge.svg) -![Black status badge](https://github.com/Hochfrequenz/bo4e-python-orm/workflows/Formatting/badge.svg) +![Formatting status badge](https://github.com/Hochfrequenz/bo4e-python-orm/workflows/Formatting/badge.svg) At this point this repository serves only as an exemplary implementation of a BO4E ORM. The main work (i.e. the generation of SQL Model code) will be done in the [BO4E-CLI-Tool](https://github.com/bo4e/BO4E-CLI) diff --git a/pyproject.toml b/pyproject.toml index 7a2e14d..2adb07e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,15 +35,32 @@ dynamic = ["readme", "version"] Changelog = "https://github.com/Hochfrequenz/bo4e-python-orm/releases" Homepage = "https://github.com/Hochfrequenz/bo4e-python-orm" -[tool.black] +[tool.ruff] line-length = 120 +extend-exclude = ["*.md"] -[tool.isort] -line_length = 120 -profile = "black" +[tool.ruff.lint] +select = ["E", "W", "F", "I", "UP", "B", "N", "PL", "RUF"] +ignore = [ + "PLR0913", # too-many-arguments + "PLR0917", # too-many-positional-arguments + "PLR0912", # too-many-branches + "PLR0915", # too-many-statements + "RUF001", # ambiguous-unicode-character-string + "RUF002", # ambiguous-unicode-character-docstring + "RUF003", # ambiguous-unicode-character-comment +] + +[tool.ruff.lint.isort] +# src/borm/models is only generated by some CI jobs' "Generate BO4E models" step, so whether +# "borm.models" resolves on disk - and thus whether ruff's isort classifies it as first-party - +# depends on which job runs. Pinning it here keeps import-sort order consistent across jobs. +known-first-party = ["borm"] -[tool.pylint."MESSAGES CONTROL"] -max-line-length = 120 +[tool.ruff.lint.per-file-ignores] +# src/borm/models is autogenerated from the BO4E schemas at CI time (not present in this checkout); +# mirrors the old .pylintrc_autogen_code disables (unused-import, line-too-long). +"src/borm/models/**" = ["F401", "E501"] [build-system] requires = ["hatchling>=1.31.0", "hatch-vcs", "hatch-fancy-pypi-readme"] @@ -56,18 +73,13 @@ tests = [ coverage = [ "coverage==7.15.2" ] -formatting = [ - "black==26.5.1", - "isort==5.13.2" -] init_bo4e = [ "bo4e-python-generator==0.0.13", "bo4e-schema-tool==0.0.9", "datamodel-code-generator==0.25.9" ] linting = [ - "pylint==4.0.6", - {include-group = "tests"} + "ruff==0.16.0", ] spell_check = [ "codespell==2.4.3" @@ -80,7 +92,6 @@ dev = [ "pre-commit", {include-group = "tests"}, {include-group = "coverage"}, - {include-group = "formatting"}, {include-group = "init_bo4e"}, {include-group = "linting"}, {include-group = "spell_check"}, diff --git a/src/borm/db/base_class.py b/src/borm/db/base_class.py index 3e183a3..521db46 100644 --- a/src/borm/db/base_class.py +++ b/src/borm/db/base_class.py @@ -14,4 +14,5 @@ class MappingBase(DeclarativeBase): """ Base class which inherits from DeclarativeBase """ + metadata = metadata diff --git a/src/borm/db/mysql_db/alembic.ini b/src/borm/db/mysql_db/alembic.ini index 90f8702..65c65e0 100644 --- a/src/borm/db/mysql_db/alembic.ini +++ b/src/borm/db/mysql_db/alembic.ini @@ -17,11 +17,11 @@ version_path_separator = os.pathsep # Use os.pathsep. Default configuration use # on newly generated revision scripts. See the documentation for further # detail and examples -# format using "black" - use the console_scripts runner, against the "black" entrypoint -hooks = black -black.type = console_scripts -black.entrypoint = black -black.options = -l 120 REVISION_SCRIPT_FILENAME +# format using "ruff format" - use the exec runner, against the "ruff" executable on PATH +hooks = ruff_format +ruff_format.type = exec +ruff_format.executable = ruff +ruff_format.options = format REVISION_SCRIPT_FILENAME # Logging configuration [loggers] diff --git a/src/borm/db/mysql_db/auxiliary.py b/src/borm/db/mysql_db/auxiliary.py index 590d74c..0ae3136 100644 --- a/src/borm/db/mysql_db/auxiliary.py +++ b/src/borm/db/mysql_db/auxiliary.py @@ -18,7 +18,7 @@ def get_url() -> str: port = os.getenv("MYSQL_PORT") db = os.getenv("MYSQL_DB") if user is None and password is None and server is None and db is None and port is None: - raise IOError("Could not load .env file.") + raise OSError("Could not load .env file.") if user is None or password is None or server is None or db is None or port is None: raise KeyError( f"Couldn't find all environment variables:\n" diff --git a/src/borm/db/mysql_db/migrations/versions/d73a00baaa17_init.py b/src/borm/db/mysql_db/migrations/versions/d73a00baaa17_init.py index 2e2e55c..83d466c 100644 --- a/src/borm/db/mysql_db/migrations/versions/d73a00baaa17_init.py +++ b/src/borm/db/mysql_db/migrations/versions/d73a00baaa17_init.py @@ -6,16 +6,13 @@ """ -from typing import Sequence, Union - -import sqlalchemy as sa -from alembic import op +from collections.abc import Sequence # revision identifiers, used by Alembic. revision: str = "d73a00baaa17" -down_revision: Union[str, None] = None -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None +down_revision: str | None = None +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None def upgrade() -> None: diff --git a/src/borm/db/postgresql_db/alembic.ini b/src/borm/db/postgresql_db/alembic.ini index 5ecfbef..ed36924 100644 --- a/src/borm/db/postgresql_db/alembic.ini +++ b/src/borm/db/postgresql_db/alembic.ini @@ -20,11 +20,11 @@ version_path_separator = os.pathsep # Use os.pathsep. Default configuration use # on newly generated revision scripts. See the documentation for further # detail and examples -# format using "black" - use the console_scripts runner, against the "black" entrypoint -hooks = black -black.type = console_scripts -black.entrypoint = black -black.options = -l 120 REVISION_SCRIPT_FILENAME +# format using "ruff format" - use the exec runner, against the "ruff" executable on PATH +hooks = ruff_format +ruff_format.type = exec +ruff_format.executable = ruff +ruff_format.options = format REVISION_SCRIPT_FILENAME # Logging configuration [loggers] diff --git a/src/borm/db/postgresql_db/auxiliary.py b/src/borm/db/postgresql_db/auxiliary.py index e3e811e..e6aee66 100644 --- a/src/borm/db/postgresql_db/auxiliary.py +++ b/src/borm/db/postgresql_db/auxiliary.py @@ -18,7 +18,7 @@ def get_url() -> str: port = os.getenv("POSTGRES_PORT") database = os.getenv("POSTGRES_DB") if user is None and password is None and server is None and database is None and port is None: - raise IOError("Could not load .env file.") + raise OSError("Could not load .env file.") if user is None or password is None or server is None or database is None or port is None: raise KeyError( f"Couldn't find all environment variables:\n" diff --git a/src/borm/db/postgresql_db/migrations/versions/9f7a0a61d21e_init.py b/src/borm/db/postgresql_db/migrations/versions/9f7a0a61d21e_init.py index c12e5ad..dd47116 100644 --- a/src/borm/db/postgresql_db/migrations/versions/9f7a0a61d21e_init.py +++ b/src/borm/db/postgresql_db/migrations/versions/9f7a0a61d21e_init.py @@ -6,16 +6,13 @@ """ -from typing import Sequence, Union - -import sqlalchemy as sa -from alembic import op +from collections.abc import Sequence # revision identifiers, used by Alembic. revision: str = "9f7a0a61d21e" -down_revision: Union[str, None] = None -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None +down_revision: str | None = None +branch_labels: str | Sequence[str] | None = None +depends_on: str | Sequence[str] | None = None def upgrade() -> None: diff --git a/tests/.pylintrc b/tests/.pylintrc deleted file mode 100644 index f6cc96b..0000000 --- a/tests/.pylintrc +++ /dev/null @@ -1,11 +0,0 @@ -[pylint] -# for the unittests disable some pylint warnings, e.g. we don't want to force devs to write docstrings for every test -disable = - C0114, # disable missing-module-docstring - C0115, # disable missing-class-docstring - C0116, # disable missing-function-docstring - R0903, # disable too-few-public-methods - W0621, # disable redefined-outer-name (this is for the use of pytest fixtures) - R0801, # disable duplicate-code (we prefer our test to be explicit rather than perfectly redundancy free) -[pylint."MESSAGES CONTROL"] -max-line-length = 120 diff --git a/tests/integrationtests/conftest.py b/tests/integrationtests/conftest.py index 88e0210..073e3ff 100644 --- a/tests/integrationtests/conftest.py +++ b/tests/integrationtests/conftest.py @@ -1,4 +1,4 @@ -from typing import Generator +from collections.abc import Generator import pytest from sqlmodel import Session, SQLModel diff --git a/uv.lock b/uv.lock index 8483fad..1d271b5 100644 --- a/uv.lock +++ b/uv.lock @@ -82,15 +82,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/66/40/c53deb2cd0c9b0fb636d24d9f40924cf2e65028e6b20b10cd5c1eeb2c730/ast_serialize-0.6.0-cp39-abi3-win_arm64.whl", hash = "sha256:ccd132fe8db56f61fe743b1f644d01b8d65b83248a8da506f3132bda86d6ed5e", size = 1072965, upload-time = "2026-06-30T20:02:54.097Z" }, ] -[[package]] -name = "astroid" -version = "4.0.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/07/63/0adf26577da5eff6eb7a177876c1cfa213856be9926a000f65c4add9692b/astroid-4.0.4.tar.gz", hash = "sha256:986fed8bcf79fb82c78b18a53352a0b287a73817d6dbcfba3162da36667c49a0", size = 406358, upload-time = "2026-02-07T23:35:07.509Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/cf/1c5f42b110e57bc5502eb80dbc3b03d256926062519224835ef08134f1f9/astroid-4.0.4-py3-none-any.whl", hash = "sha256:52f39653876c7dec3e3afd4c2696920e05c83832b9737afc21928f2d2eb7a753", size = 276445, upload-time = "2026-02-07T23:35:05.344Z" }, -] - [[package]] name = "black" version = "26.5.1" @@ -179,21 +170,15 @@ coverage = [ { name = "coverage" }, ] dev = [ - { name = "black" }, { name = "bo4e-python-generator" }, { name = "bo4e-schema-tool" }, { name = "codespell" }, { name = "coverage" }, { name = "datamodel-code-generator" }, - { name = "isort" }, { name = "mypy" }, { name = "pre-commit" }, - { name = "pylint" }, { name = "pytest" }, -] -formatting = [ - { name = "black" }, - { name = "isort" }, + { name = "ruff" }, ] init-bo4e = [ { name = "bo4e-python-generator" }, @@ -201,8 +186,7 @@ init-bo4e = [ { name = "datamodel-code-generator" }, ] linting = [ - { name = "pylint" }, - { name = "pytest" }, + { name = "ruff" }, ] spell-check = [ { name = "codespell" }, @@ -233,31 +217,22 @@ requires-dist = [ [package.metadata.requires-dev] coverage = [{ name = "coverage", specifier = "==7.15.2" }] dev = [ - { name = "black", specifier = "==26.5.1" }, { name = "bo4e-python-generator", specifier = "==0.0.13" }, { name = "bo4e-schema-tool", specifier = "==0.0.9" }, { name = "codespell", specifier = "==2.4.3" }, { name = "coverage", specifier = "==7.15.2" }, { name = "datamodel-code-generator", specifier = "==0.25.9" }, - { name = "isort", specifier = "==5.13.2" }, { name = "mypy", specifier = "==2.3.0" }, { name = "pre-commit" }, - { name = "pylint", specifier = "==4.0.6" }, { name = "pytest", specifier = "==9.1.1" }, -] -formatting = [ - { name = "black", specifier = "==26.5.1" }, - { name = "isort", specifier = "==5.13.2" }, + { name = "ruff", specifier = "==0.16.0" }, ] init-bo4e = [ { name = "bo4e-python-generator", specifier = "==0.0.13" }, { name = "bo4e-schema-tool", specifier = "==0.0.9" }, { name = "datamodel-code-generator", specifier = "==0.25.9" }, ] -linting = [ - { name = "pylint", specifier = "==4.0.6" }, - { name = "pytest", specifier = "==9.1.1" }, -] +linting = [{ name = "ruff", specifier = "==0.16.0" }] spell-check = [{ name = "codespell", specifier = "==2.4.3" }] tests = [{ name = "pytest", specifier = "==9.1.1" }] type-check = [ @@ -657,15 +632,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b9/68/b3ade2468b649a78561ec2f64222a32d27c83d2e3612cc1846703d489ffd/datamodel_code_generator-0.25.9-py3-none-any.whl", hash = "sha256:9e0324233123d6e39a35bc0004771956935889a974aacfd7a0651de11d2219a9", size = 110721, upload-time = "2024-08-07T03:11:02.237Z" }, ] -[[package]] -name = "dill" -version = "0.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/81/e1/56027a71e31b02ddc53c7d65b01e68edf64dea2932122fe7746a516f75d5/dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa", size = 187315, upload-time = "2026-01-19T02:36:56.85Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/77/dc8c558f7593132cf8fefec57c4f60c83b16941c574ac5f619abb3ae7933/dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d", size = 120019, upload-time = "2026-01-19T02:36:55.663Z" }, -] - [[package]] name = "distlib" version = "0.4.3" @@ -689,8 +655,8 @@ name = "email-validator" version = "2.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "dnspython", marker = "python_full_version < '4'" }, - { name = "idna", marker = "python_full_version < '4'" }, + { name = "dnspython" }, + { name = "idna" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } wheels = [ @@ -1010,15 +976,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, ] -[[package]] -name = "mccabe" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, -] - [[package]] name = "more-itertools" version = "11.1.0" @@ -1189,7 +1146,7 @@ wheels = [ [package.optional-dependencies] email = [ - { name = "email-validator", marker = "python_full_version < '4'" }, + { name = "email-validator" }, ] [[package]] @@ -1342,24 +1299,6 @@ crypto = [ { name = "cryptography" }, ] -[[package]] -name = "pylint" -version = "4.0.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "astroid" }, - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "dill" }, - { name = "isort" }, - { name = "mccabe" }, - { name = "platformdirs" }, - { name = "tomlkit" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7d/1d/3bb57f303701549550d74bf7ced2b07412be97125c167a0c9d216aa9f762/pylint-4.0.6.tar.gz", hash = "sha256:52f19191bee08bf103f9705ad1a0ece4aa5a0a4ef2bdcbd969375a1e6f6579d5", size = 1585588, upload-time = "2026-06-14T14:43:26.772Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/da/acb2e7d4dbd2dfb792d38c0d850481f29ad7049b356d23f56c687d35203b/pylint-4.0.6-py3-none-any.whl", hash = "sha256:d11a0e1fdb7b1cd46ec5d6fc78fee8b95f28695b2d6140e5809925f61e32ea54", size = 538389, upload-time = "2026-06-14T14:43:24.873Z" }, -] - [[package]] name = "pymysql" version = "1.2.0" @@ -1546,6 +1485,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, ] +[[package]] +name = "ruff" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4d/94/1e5e4967626faf12fa56999cd6222dff6992ceb086ad7945756baf70c7a7/ruff-0.16.0.tar.gz", hash = "sha256:e460aafd5495ec89efaa6ced2e4a9a581116451e1c88b9d37ef497e0f8e93982", size = 4790557, upload-time = "2026-07-23T19:11:30.981Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/81/1c8818fee7ce1a04cd7d1b3172e0a8f8e4f1dc4feb7fc390e16daa8af323/ruff-0.16.0-py3-none-linux_armv6l.whl", hash = "sha256:e5115729eb08c585e5121978ba5d5b60caeae394ce21b9fb5e6cd33a1c6c9b1e", size = 10754633, upload-time = "2026-07-23T19:10:46.415Z" }, + { url = "https://files.pythonhosted.org/packages/23/df/beaf59c09d68db84304d555f188b276a77132a5d5b0b67a5c762aa143628/ruff-0.16.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3c954b1d580bfa035b41654f7858cc7e71d5fc3ac5b723dd62bd9133830ed522", size = 10969164, upload-time = "2026-07-23T19:10:50.271Z" }, + { url = "https://files.pythonhosted.org/packages/42/ce/741cd197496a1abbf51352710fd15ed995d2a2be87189c1da26a450d6e83/ruff-0.16.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e01c21d10eb1b29f47b7454e1f4056db9a3f0260c646aa88457c610291db9f81", size = 10488846, upload-time = "2026-07-23T19:10:52.639Z" }, + { url = "https://files.pythonhosted.org/packages/52/2a/a2db8e88cade358f5cdcb05674a917751074109315d014eb6352d9a893f7/ruff-0.16.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e364e5ed22ed8dc05082fd78e35308618260907ac2d3c1d637b2e682415b6c9", size = 10889729, upload-time = "2026-07-23T19:10:54.89Z" }, + { url = "https://files.pythonhosted.org/packages/42/65/62a771694ebd63029dc953e27dbad40e1588bd4860ff9fe881018fddaa49/ruff-0.16.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d327b8fc113a1d4421a04f3839d3752057c8dd1ee320223a6f3f52d04ada462a", size = 10568275, upload-time = "2026-07-23T19:10:56.993Z" }, + { url = "https://files.pythonhosted.org/packages/3f/e2/ced249fe8af5f086c5c58cc21cc3356d50f32f7401c5df87050c999620a7/ruff-0.16.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9b50c55e263103586b3dcf5f73d479eb8cb5fdb6098fec59a62891dab653717", size = 11385112, upload-time = "2026-07-23T19:10:59.615Z" }, + { url = "https://files.pythonhosted.org/packages/87/0b/05154977a8fd69eeb6c103271f55403bfd8711f5c0f8ed07489d95a504e7/ruff-0.16.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ff4a79ce3ec0172f3241943835de1c4cb4e2dcd07f0f8c2d02603dbbbee4b17", size = 12207008, upload-time = "2026-07-23T19:11:02.154Z" }, + { url = "https://files.pythonhosted.org/packages/fb/29/98225831a3a1eab0e02f4acc6ca6559a98611dcc68b6965ff4b7234627c1/ruff-0.16.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e95c448fca1fb2a18372a9440926c5a6ee789639bb975c72e7ae6d0b04218ab4", size = 11650842, upload-time = "2026-07-23T19:11:04.557Z" }, + { url = "https://files.pythonhosted.org/packages/91/66/6bd3cf90500653d55dc0ffc8507aa8300bd49d0214b2e8cb4d3fef2943ba/ruff-0.16.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f11a8d11010301d0a398a2fdef67691feca7294da6aef55e2150e8fa2cd520b", size = 11400718, upload-time = "2026-07-23T19:11:09.233Z" }, + { url = "https://files.pythonhosted.org/packages/8e/a2/a54eb4eae05d66364050a5d3b8a9c5ef88196531b3cbe7109d873f87f819/ruff-0.16.0-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:48044c678e9cb8698246c99b14aaccfa6601dea7379eb48a6f8f73f7a6d86cd0", size = 11426177, upload-time = "2026-07-23T19:11:11.994Z" }, + { url = "https://files.pythonhosted.org/packages/1a/be/16e3eea4b2a478a496919f5e36f17c4559e54620bd3bbac5d6affa068006/ruff-0.16.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7aa0959bad8eb8bef50340154fc9b58678dae31fa4293afa38b44b6e552c0213", size = 10856126, upload-time = "2026-07-23T19:11:14.221Z" }, + { url = "https://files.pythonhosted.org/packages/a2/84/252eb8b868a16eec7257c14f504f77537e734b2d69c762e639e588e304a3/ruff-0.16.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:28ea2b7df8ebf7f9da6b7d47b230ab48f387c0a29be3b474c4d0740e197bb9af", size = 10571208, upload-time = "2026-07-23T19:11:16.378Z" }, + { url = "https://files.pythonhosted.org/packages/21/09/817a482f542f7570cbb4554b26e896610c7114f539b1d9e2d2145bf6bef6/ruff-0.16.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:33a3dfac8c35f81498dea9181bccc2f4c4bc8f1521a1dd9406e77643e0f0fb09", size = 11063329, upload-time = "2026-07-23T19:11:19.173Z" }, + { url = "https://files.pythonhosted.org/packages/2e/23/9403c180ca1cb9b1f7335f5c3e5305c09d49ea5b345196682a36028bde4a/ruff-0.16.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a5237a0bda500d30d81b8e07a6973a5cbc772864cbf746ae2f4e8a2e01c9f4ed", size = 11489751, upload-time = "2026-07-23T19:11:21.74Z" }, + { url = "https://files.pythonhosted.org/packages/b2/1d/1b2ef7bcde851c78d7f17f1cca13fd6dc695fc4b3d6197941e72cae5b132/ruff-0.16.0-py3-none-win32.whl", hash = "sha256:7fab76fa065c873f41ff744347c6e77bcc3dfec4bcc754dc26b63d23c0f7f5fb", size = 10785885, upload-time = "2026-07-23T19:11:23.947Z" }, + { url = "https://files.pythonhosted.org/packages/b2/a3/d5e4ef7a56be3f928ffb90b94c25ba7d3cb9c7fe0736aeaaedf361770712/ruff-0.16.0-py3-none-win_amd64.whl", hash = "sha256:429c117f022bf481fabd9d551e7a3952b24c65e6ef44337ea09d90bebef14472", size = 11923141, upload-time = "2026-07-23T19:11:26.409Z" }, + { url = "https://files.pythonhosted.org/packages/cb/9a/8415f2657cbe200f41a4531ccededf135505a92d4a012229121f885b26f9/ruff-0.16.0-py3-none-win_arm64.whl", hash = "sha256:14296fedcd2705c77ab8235439278bbb38f285cf7da5528b00b3e330c3d4872d", size = 11273407, upload-time = "2026-07-23T19:11:28.705Z" }, +] + [[package]] name = "sqlalchemy" version = "2.0.51" @@ -1608,15 +1572,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cf/7d/b9813a582d4eb310be35e1fc7dfaae71207d7b62e9e53be314ebd251b53b/sqlmodel-0.0.39-py3-none-any.whl", hash = "sha256:90ebe92ce5cc11d7fff8dc7cb594790a102333c8fe7c14865254f6fc5c939795", size = 29680, upload-time = "2026-06-25T13:01:37.494Z" }, ] -[[package]] -name = "tomlkit" -version = "0.15.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/96/e07752635b98536177fa1f37671c8f3cdde2e724c6bcf6034b2cfb571565/tomlkit-0.15.1.tar.gz", hash = "sha256:e25bbf38843005246210a12982776f27f99cb9be67160e14434d0c0d21ee1e97", size = 180129, upload-time = "2026-07-17T01:48:04.562Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/bc/8c13eb66537dce1d2bd3a57132902f38d0e7f5bb46fa9f4daed9fe9d76ee/tomlkit-0.15.1-py3-none-any.whl", hash = "sha256:177a05aece5a8ca5266fd3c448abb47b8d352f09d477d3ca8332db4d89b24304", size = 49449, upload-time = "2026-07-17T01:48:05.728Z" }, -] - [[package]] name = "typing-extensions" version = "4.16.0"