diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 3db7370..8e47003 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -9,6 +9,11 @@ defaults: run: shell: bash +env: + # python version for dev workspace + DEV_WORKSPACE_PYTHON_VERSION: '3.13' + + jobs: build: runs-on: ${{ matrix.os }} @@ -17,7 +22,6 @@ jobs: max-parallel: 1 matrix: os: [ubuntu-24.04, macos-13, windows-2022] - python-version: ["3.13"] include: - os: ubuntu-24.04 name: Linux @@ -29,150 +33,39 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Install poetry - run: pipx install poetry==2.1.2 - - - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python ${{ env.DEV_WORKSPACE_PYTHON_VERSION }} uses: actions/setup-python@v5 with: - python-version: ${{ matrix.python-version }} - cache: "poetry" + python-version: ${{ env.DEV_WORKSPACE_PYTHON_VERSION }} - name: Install dependencies run: | - # poetry default git client `dulwich` doesn't work properly with git urls - # to dependencies, which we use - poetry config system-git-client true - - FINECODE_SH_TEMPLATE="poetry run python" - - poetry install - echo $FINECODE_SH_TEMPLATE > finecode.sh - - pushd tests/list_ws/backend - poetry install - echo $FINECODE_SH_TEMPLATE > finecode.sh - popd - - pushd tests/list_ws/cli_tool - poetry install - echo $FINECODE_SH_TEMPLATE > finecode.sh - popd - - pushd tests/list_ws/ui_app - poetry install - echo $FINECODE_SH_TEMPLATE > finecode.sh - popd - - pushd tests/nested_package/pyback - poetry install - echo $FINECODE_SH_TEMPLATE > finecode.sh - popd + python -m venv .venvs/dev_workspace + source .venvs/dev_workspace/bin/activate + python -m pip install --upgrade pip==25.1.1 + python -m pip install --group="dev_workspace" - pushd finecode_extension_api - poetry install - echo $FINECODE_SH_TEMPLATE > finecode.sh - popd + python -m finecode prepare-envs shell: bash + # TODO: install all other supported python versions. Version can be extracted from finecode + # - name: Lint # run: | # poetry run python -m finecode run lint # shell: bash - - name: Build finecode_extension_api - if: runner.os == 'Linux' - run: | - pushd finecode_extension_api - poetry build - popd - shell: bash - - - name: Build fine_python_ast - if: runner.os == 'Linux' - run: | - pushd extensions/fine_python_ast - poetry build - popd - shell: bash - - - name: Build fine_python_black - if: runner.os == 'Linux' - run: | - pushd extensions/fine_python_black - poetry build - popd - shell: bash - - - name: Build fine_python_flake8 - if: runner.os == 'Linux' - run: | - pushd extensions/fine_python_flake8 - poetry build - popd - shell: bash - - - name: Build fine_python_isort + - name: Build all packages if: runner.os == 'Linux' run: | - pushd extensions/fine_python_isort - poetry build - popd - shell: bash - - - name: Build fine_python_module_exports - if: runner.os == 'Linux' - run: | - pushd extensions/fine_python_module_exports - poetry build - popd - shell: bash - - - name: Build fine_python_mypy - if: runner.os == 'Linux' - run: | - pushd extensions/fine_python_mypy - poetry build - popd - shell: bash - - - name: Build fine_python_format - if: runner.os == 'Linux' - run: | - pushd presets/fine_python_format - poetry build - popd - shell: bash - - - name: Build fine_python_lint - if: runner.os == 'Linux' - run: | - pushd presets/fine_python_lint - poetry build - popd - shell: bash - - - name: Build fine_python_recommended - if: runner.os == 'Linux' - run: | - pushd presets/fine_python_recommended - poetry build - popd - shell: bash - - - name: Build finecode - if: runner.os == 'Linux' - run: | - python -m venv .dev_workspace_venv - source .dev_workspace_venv/bin/activate - python -m pip install --upgrade pip==25.1.1 - python -m pip install --group="dev_workspace" - python -m build + source .venvs/dev_workspace/bin/activate + python -m finecode run build shell: bash - name: Collect all distribution packages if: runner.os == 'Linux' run: | + # TODO: finecode action to copy only updated packages in dist mkdir -p dist cp finecode_extension_api/dist/* dist/ cp extensions/fine_python_ast/dist/* dist/ diff --git a/.gitignore b/.gitignore index 0f6425a..3418202 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,8 @@ __pycache__ dist src/finecode/_version.py -src/finecode.egg-info \ No newline at end of file +src/finecode.egg-info + +.venvs +finecode_config_dump/ +build/ \ No newline at end of file diff --git a/.python-version b/.python-version deleted file mode 100644 index 2c07333..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.11 diff --git a/README.md b/README.md index ec0832b..8e3a471 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # FineCode -**Status Update (04.06.2025):** FineCode is available for use, but the current version is intended only for personal testing, not for production use, as we actively work on improving execution environments, which will undergo significant changes. Initial release with new execution environments is expected in July 2025. - ## Personalize and improve your development experience FineCode is a tool runner and set of utilities for creating tools for software developers. @@ -23,7 +21,7 @@ With FineCode you can: dev_workspace = ["finecode==0.2.*"] ``` -1.1.2 Create dev_workspace venv: `python -m venv .venvs/dev_workspace` (https://docs.python.org/3/library/venv.html#creating-virtual-environments ) +1.1.2 Create dev_workspace venv: `python -m venv .venvs/dev_workspace` ([Python Docs](https://docs.python.org/3/library/venv.html#creating-virtual-environments )) 1.1.3 Activate this venv and install dependencies from `dev_workspace` group: ``` @@ -45,10 +43,10 @@ NOTE: `pip install` supports `--group` parameter since pip 25.1. Make sure you h For list of presets from FineCode authors see 'Presets' section below. -1.2.1 Run `prepare_env` finecode action: +1.2.1 Run `prepare-envs` finecode command: ```bash - python -m finecode run prepare_env + python -m finecode prepare-envs ``` 1.3 Enable finecode and preset diff --git a/extensions/fine_python_ast/fine_python_ast/__init__.py b/extensions/fine_python_ast/fine_python_ast/__init__.py index 369f6e6..11e60c2 100644 --- a/extensions/fine_python_ast/fine_python_ast/__init__.py +++ b/extensions/fine_python_ast/fine_python_ast/__init__.py @@ -1,5 +1,5 @@ -from .iast_provider import IPythonSingleAstProvider from .ast_provider import PythonSingleAstProvider +from .iast_provider import IPythonSingleAstProvider __all__ = [ "IPythonSingleAstProvider", diff --git a/extensions/fine_python_ast/poetry.lock b/extensions/fine_python_ast/poetry.lock deleted file mode 100644 index 142ee8b..0000000 --- a/extensions/fine_python_ast/poetry.lock +++ /dev/null @@ -1,195 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "finecode_extension_api-0.1.0-py3-none-any.whl", hash = "sha256:55d4448a1a2f7224c3fdf05879fa9782246c0a85dc1dfb17543374fd808c2b5b"}, - {file = "finecode_extension_api-0.1.0.tar.gz", hash = "sha256:dee16c180e4cd318f71bf7a94b6ae425667153f8fb62630ab60db9b034f45595"}, -] - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[[package]] -name = "pydantic" -version = "2.11.4" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb"}, - {file = "pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.33.2" -typing-extensions = ">=4.12.2" -typing-inspection = ">=0.4.0" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.33.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, - {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "typing-inspection" -version = "0.4.0" -description = "Runtime typing introspection tools" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"}, - {file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"}, -] - -[package.dependencies] -typing-extensions = ">=4.12.0" - -[metadata] -lock-version = "2.1" -python-versions = ">=3.11, < 3.14" -content-hash = "241dec2b0848003a1d8b7850c58ca611633cac908f00077dc383d8a223a499df" diff --git a/extensions/fine_python_ast/pyproject.toml b/extensions/fine_python_ast/pyproject.toml index a19fde1..1e76cf6 100644 --- a/extensions/fine_python_ast/pyproject.toml +++ b/extensions/fine_python_ast/pyproject.toml @@ -1,13 +1,8 @@ [project] name = "fine-python-ast" -version = "0.1.0" +version = "0.2.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">=3.11, < 3.14" -dependencies = ["finecode_extension_api==0.1.0"] - - -[build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +dependencies = ["finecode_extension_api==0.3.*"] diff --git a/extensions/fine_python_ast/setup.py b/extensions/fine_python_ast/setup.py new file mode 100644 index 0000000..50212ce --- /dev/null +++ b/extensions/fine_python_ast/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_ast", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/extensions/fine_python_black/fine_python_black/__init__.py b/extensions/fine_python_black/fine_python_black/__init__.py index 5c3b020..5ad85fe 100644 --- a/extensions/fine_python_black/fine_python_black/__init__.py +++ b/extensions/fine_python_black/fine_python_black/__init__.py @@ -1,7 +1,4 @@ -from .action import ( - BlackFormatHandler, - BlackFormatHandlerConfig, -) +from .action import BlackFormatHandler, BlackFormatHandlerConfig __all__ = [ "BlackFormatHandler", diff --git a/extensions/fine_python_black/fine_python_black/action.py b/extensions/fine_python_black/fine_python_black/action.py index 839c01c..7899e63 100644 --- a/extensions/fine_python_black/fine_python_black/action.py +++ b/extensions/fine_python_black/fine_python_black/action.py @@ -1,5 +1,6 @@ from __future__ import annotations +import dataclasses import sys # import asyncio @@ -41,6 +42,7 @@ def get_black_mode(config: BlackFormatHandlerConfig) -> Mode: ) +@dataclasses.dataclass class BlackFormatHandlerConfig(code_action.ActionHandlerConfig): # TODO: should be set target_versions: list[ @@ -48,7 +50,7 @@ class BlackFormatHandlerConfig(code_action.ActionHandlerConfig): # Literal["PY33", "PY34", "PY35", "PY36", "PY37", # "PY38", "PY39", "PY310", "PY311", "PY312"] str - ] = [] + ] = dataclasses.field(default_factory=list) # default black line length is 88: # https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#line-length line_length: int = 88 diff --git a/extensions/fine_python_black/poetry.lock b/extensions/fine_python_black/poetry.lock deleted file mode 100644 index b536707..0000000 --- a/extensions/fine_python_black/poetry.lock +++ /dev/null @@ -1,321 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "black" -version = "25.1.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, - {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, - {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, - {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, - {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, - {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, - {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, - {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, - {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, - {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, - {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, - {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, - {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, - {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, - {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, - {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, - {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, - {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, - {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, - {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, - {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, - {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "click" -version = "8.2.0" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.10" -groups = ["main"] -files = [ - {file = "click-8.2.0-py3-none-any.whl", hash = "sha256:6b303f0b2aa85f1cb4e5303078fadcbcd4e476f114fab9b5007005711839325c"}, - {file = "click-8.2.0.tar.gz", hash = "sha256:f5452aeddd9988eefa20f90f05ab66f17fce1ee2a36907fd30b05bbb5953814d"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -markers = "platform_system == \"Windows\"" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "finecode_extension_api-0.1.0-py3-none-any.whl", hash = "sha256:55d4448a1a2f7224c3fdf05879fa9782246c0a85dc1dfb17543374fd808c2b5b"}, - {file = "finecode_extension_api-0.1.0.tar.gz", hash = "sha256:dee16c180e4cd318f71bf7a94b6ae425667153f8fb62630ab60db9b034f45595"}, -] - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.3.8" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, - {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] - -[[package]] -name = "pydantic" -version = "2.11.4" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb"}, - {file = "pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.33.2" -typing-extensions = ">=4.12.2" -typing-inspection = ">=0.4.0" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.33.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, - {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "typing-inspection" -version = "0.4.0" -description = "Runtime typing introspection tools" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"}, - {file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"}, -] - -[package.dependencies] -typing-extensions = ">=4.12.0" - -[metadata] -lock-version = "2.1" -python-versions = ">=3.11, < 3.14" -content-hash = "68cdb47eb2b61e9c00e52260c49119fd85326a2d471c39b4729430d7714ac637" diff --git a/extensions/fine_python_black/pyproject.toml b/extensions/fine_python_black/pyproject.toml index 2b79dfe..779196f 100644 --- a/extensions/fine_python_black/pyproject.toml +++ b/extensions/fine_python_black/pyproject.toml @@ -1,13 +1,8 @@ [project] name = "fine_python_black" -version = "0.1.0" +version = "0.2.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">=3.11, < 3.14" -dependencies = ["finecode_extension_api==0.1.0", "black (>=25.1.0,<26.0.0)"] - - -[build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +dependencies = ["finecode_extension_api==0.3.*", "black (>=25.1.0,<26.0.0)"] diff --git a/extensions/fine_python_black/setup.py b/extensions/fine_python_black/setup.py new file mode 100644 index 0000000..52a16dc --- /dev/null +++ b/extensions/fine_python_black/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_black", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/extensions/fine_python_flake8/fine_python_flake8/action.py b/extensions/fine_python_flake8/fine_python_flake8/action.py index 630ad32..8e54c4c 100644 --- a/extensions/fine_python_flake8/fine_python_flake8/action.py +++ b/extensions/fine_python_flake8/fine_python_flake8/action.py @@ -2,6 +2,7 @@ import argparse import ast +import dataclasses import operator from pathlib import Path @@ -106,6 +107,7 @@ def run_flake8_on_single_file( return lint_messages +@dataclasses.dataclass class Flake8LintHandlerConfig(code_action.ActionHandlerConfig): max_line_length: int = 79 extend_select: list[str] | None = None diff --git a/extensions/fine_python_flake8/poetry.lock b/extensions/fine_python_flake8/poetry.lock deleted file mode 100644 index b403632..0000000 --- a/extensions/fine_python_flake8/poetry.lock +++ /dev/null @@ -1,290 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "fine-python-ast" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_ast-0.1.0-py3-none-any.whl", hash = "sha256:3dcdcdc40ed89e0b90686f2ad5d358d8edba622a5de4c1f52f2f0787dcc4e07d"}, - {file = "fine_python_ast-0.1.0.tar.gz", hash = "sha256:ebc68aef7d0379f8771f610e436f6075b7c299a8895f1b9b7769fd038f95397e"}, -] - -[package.dependencies] -finecode_extension_api = "0.1.0" - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "finecode_extension_api-0.1.0-py3-none-any.whl", hash = "sha256:55d4448a1a2f7224c3fdf05879fa9782246c0a85dc1dfb17543374fd808c2b5b"}, - {file = "finecode_extension_api-0.1.0.tar.gz", hash = "sha256:dee16c180e4cd318f71bf7a94b6ae425667153f8fb62630ab60db9b034f45595"}, -] - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[[package]] -name = "flake8" -version = "7.2.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343"}, - {file = "flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.13.0,<2.14.0" -pyflakes = ">=3.3.0,<3.4.0" - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "pycodestyle" -version = "2.13.0" -description = "Python style guide checker" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9"}, - {file = "pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae"}, -] - -[[package]] -name = "pydantic" -version = "2.11.4" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb"}, - {file = "pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.33.2" -typing-extensions = ">=4.12.2" -typing-inspection = ">=0.4.0" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.33.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, - {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pyflakes" -version = "3.3.2" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a"}, - {file = "pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b"}, -] - -[[package]] -name = "types-flake8" -version = "7.2.0.20250330" -description = "Typing stubs for flake8" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "types_flake8-7.2.0.20250330-py3-none-any.whl", hash = "sha256:af31590a269586309b80a439c94e59359e139e17475a8fc8d3c426ab01a40547"}, - {file = "types_flake8-7.2.0.20250330.tar.gz", hash = "sha256:481e5c914a26fabd23e85704ad055f2716f9238740bfe6fe77259c2533cb970c"}, -] - -[package.dependencies] -types-pyflakes = "*" - -[[package]] -name = "types-pyflakes" -version = "3.3.2.20250511" -description = "Typing stubs for pyflakes" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "types_pyflakes-3.3.2.20250511-py3-none-any.whl", hash = "sha256:85802fdd0b64d3553ef12ac0ba02d85c4bbd38747579c544e6bb005ec455becf"}, - {file = "types_pyflakes-3.3.2.20250511.tar.gz", hash = "sha256:d0ef58f9ec15eab2a9e427814f48587be4eb2752a8ae7dec201d65086f50ace2"}, -] - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "typing-inspection" -version = "0.4.0" -description = "Runtime typing introspection tools" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"}, - {file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"}, -] - -[package.dependencies] -typing-extensions = ">=4.12.0" - -[metadata] -lock-version = "2.1" -python-versions = ">=3.11, < 3.14" -content-hash = "261b27c50864ea7935982f6a86aa5fcd65dc20e213fc2c0745e4ae4757f779ea" diff --git a/extensions/fine_python_flake8/pyproject.toml b/extensions/fine_python_flake8/pyproject.toml index 639994c..4abbac0 100644 --- a/extensions/fine_python_flake8/pyproject.toml +++ b/extensions/fine_python_flake8/pyproject.toml @@ -1,18 +1,13 @@ [project] name = "fine-python-flake8" -version = "0.1.0" +version = "0.2.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">=3.11, < 3.14" dependencies = [ - "finecode_extension_api==0.1.0", - "fine_python_ast==0.1.0", + "finecode_extension_api==0.3.*", + "fine_python_ast==0.2.*", "types-flake8 (>=7.1.0.20241020,<8.0.0.0)", "flake8 (>=7.1.2,<8.0.0)", ] - - -[build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" diff --git a/extensions/fine_python_flake8/setup.py b/extensions/fine_python_flake8/setup.py new file mode 100644 index 0000000..d42fa6d --- /dev/null +++ b/extensions/fine_python_flake8/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_flake8", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/extensions/fine_python_isort/fine_python_isort/action.py b/extensions/fine_python_isort/fine_python_isort/action.py index f3158b0..d20ec6d 100644 --- a/extensions/fine_python_isort/fine_python_isort/action.py +++ b/extensions/fine_python_isort/fine_python_isort/action.py @@ -1,5 +1,6 @@ from __future__ import annotations +import dataclasses from io import StringIO from pathlib import Path @@ -11,6 +12,7 @@ from finecode_extension_api.interfaces import icache, ilogger, iprocessexecutor +@dataclasses.dataclass class IsortFormatHandlerConfig(code_action.ActionHandlerConfig): profile: str = "" diff --git a/extensions/fine_python_isort/poetry.lock b/extensions/fine_python_isort/poetry.lock deleted file mode 100644 index 226b418..0000000 --- a/extensions/fine_python_isort/poetry.lock +++ /dev/null @@ -1,210 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "finecode_extension_api-0.1.0-py3-none-any.whl", hash = "sha256:55d4448a1a2f7224c3fdf05879fa9782246c0a85dc1dfb17543374fd808c2b5b"}, - {file = "finecode_extension_api-0.1.0.tar.gz", hash = "sha256:dee16c180e4cd318f71bf7a94b6ae425667153f8fb62630ab60db9b034f45595"}, -] - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "pydantic" -version = "2.11.4" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb"}, - {file = "pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.33.2" -typing-extensions = ">=4.12.2" -typing-inspection = ">=0.4.0" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.33.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, - {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "typing-inspection" -version = "0.4.0" -description = "Runtime typing introspection tools" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"}, - {file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"}, -] - -[package.dependencies] -typing-extensions = ">=4.12.0" - -[metadata] -lock-version = "2.1" -python-versions = ">= 3.11, < 3.14" -content-hash = "672ef3c1264ef102e64a40d92c5889fce13566cd0db5680064d7ae3e5ead2f43" diff --git a/extensions/fine_python_isort/pyproject.toml b/extensions/fine_python_isort/pyproject.toml index 8330470..b6ef046 100644 --- a/extensions/fine_python_isort/pyproject.toml +++ b/extensions/fine_python_isort/pyproject.toml @@ -1,13 +1,8 @@ [project] name = "fine-python-isort" -version = "0.1.0" +version = "0.2.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">= 3.11, < 3.14" -dependencies = ["finecode_extension_api==0.1.0", "isort (>=5.13, <6)"] - - -[build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +dependencies = ["finecode_extension_api==0.3.*", "isort (>=5.13, <6)"] diff --git a/extensions/fine_python_isort/setup.py b/extensions/fine_python_isort/setup.py new file mode 100644 index 0000000..05cef8d --- /dev/null +++ b/extensions/fine_python_isort/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_isort", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/extensions/fine_python_module_exports/fine_python_module_exports/api.py b/extensions/fine_python_module_exports/fine_python_module_exports/api.py new file mode 100644 index 0000000..9bd8fd7 --- /dev/null +++ b/extensions/fine_python_module_exports/fine_python_module_exports/api.py @@ -0,0 +1,118 @@ +""" +Here we don't validate file, we extract only valid data. Linter is responsible for +validation but we need to be aware of invalid data. +""" + +import ast +import enum + +from finecode_extension_api import common_types + + +def find_exported_members_names(module_ast: ast.Module) -> list[str] | None: + # if returns None, then there are no explicit exports + exports_found: bool = False + exported_members_names: list[str] = [] + + # '__all__' is usually at the end of file, iterate from the end + for stmt in module_ast.body[::-1]: + if isinstance(stmt, ast.Assign): + assign_target = stmt.targets[0] + if isinstance(assign_target, ast.Name) and assign_target.id == "__all__": + exports_found = True + rvalue = stmt.value + if isinstance(rvalue, ast.List): + exported_members_names = [ + item.value + for item in rvalue.elts + if isinstance(item, ast.Constant) + and isinstance(item.value, str) + ] + break + + if not exports_found: + return None + return exported_members_names + + +class ModuleMemberAccessType(enum.Enum): + PUBLIC = enum.auto() + PRIVATE = enum.auto() + # some statements like imports have no access type currently + UNKNOWN = enum.auto() + + +class PositionRelativeRange(enum.Enum): + BEFORE = enum.auto() + INSIDE = enum.auto() + AFTER = enum.auto() + + +def get_stmt_position_relative_range( + stmt: ast.stmt, range_in_doc: common_types.Range +) -> PositionRelativeRange: + # check start position of statement relative to range. Note that end of statement + # if it is multiline can be in range even with PositionRelativeRange.BEFORE. + if stmt.lineno < range_in_doc.start.line: + return PositionRelativeRange.BEFORE + elif stmt.lineno > range_in_doc.end.line: + return PositionRelativeRange.AFTER + else: + # if statement is at the first line of at the last line of range, check also + # column + if stmt.lineno == range_in_doc.start.line: + if stmt.col_offset < range_in_doc.start.character: + return PositionRelativeRange.BEFORE + else: + return PositionRelativeRange.INSIDE + elif stmt.lineno == range_in_doc.end.line: + if stmt.col_offset > range_in_doc.end.character: + return PositionRelativeRange.BEFORE + else: + return PositionRelativeRange.INSIDE + else: + return PositionRelativeRange.INSIDE + + +def get_module_members_with_access_type( + module_ast: ast.Module, + exported_members_names: list[str] | None, + range_in_doc: common_types.Range | None, +) -> dict[ast.stmt, ModuleMemberAccessType]: + module_members_with_access_type: dict[ast.stmt, ModuleMemberAccessType] = {} + default_stmt_access_type: ModuleMemberAccessType = ( + ModuleMemberAccessType.PRIVATE + if exported_members_names is not None + else ModuleMemberAccessType.PUBLIC + ) + + for stmt in module_ast.body: + stmt_name: str = "" + + if range_in_doc is not None: + relative_position: PositionRelativeRange = get_stmt_position_relative_range( + stmt, range_in_doc + ) + if relative_position == PositionRelativeRange.BEFORE: + continue + elif relative_position == PositionRelativeRange.AFTER: + break + + match stmt: + case ast.FunctionDef() | ast.AsyncFunctionDef() | ast.ClassDef(): + stmt_name = stmt.name + # TODO: assignment + # TODO: import? <- possible improvement in future + case _: + continue + + stmt_access_type: ModuleMemberAccessType = default_stmt_access_type + if exported_members_names is not None: + stmt_access_type = ( + ModuleMemberAccessType.PUBLIC + if stmt_name in exported_members_names + else ModuleMemberAccessType.PRIVATE + ) + module_members_with_access_type[stmt] = stmt_access_type + + return module_members_with_access_type diff --git a/extensions/fine_python_module_exports/fine_python_module_exports/extension.py b/extensions/fine_python_module_exports/fine_python_module_exports/extension.py new file mode 100644 index 0000000..5d35f83 --- /dev/null +++ b/extensions/fine_python_module_exports/fine_python_module_exports/extension.py @@ -0,0 +1,69 @@ +from __future__ import annotations + +import ast +from pathlib import Path + +from fine_python_ast import iast_provider +from fine_python_module_exports import api + +from finecode_extension_api import common_types +from finecode_extension_api.actions.ide import text_document_inlay_hint + +# from finecode_extension_api import code_action + +# from finecode.extension_runner.interfaces import icache + +def uri_str_to_path(uri_str: str) -> Path: + return Path(uri_str.replace("file://", "")) + + +async def get_document_inlay_hints( + payload: text_document_inlay_hint.InlayHintPayload, + ast_provider: iast_provider.IPythonSingleAstProvider, + # cache: icache.ICache +) -> text_document_inlay_hint.InlayHintResult: + """ + ~~It's cheap enough to calculate access type for the whole file, so calculate and + cache. Then get nodes and access types for asked range.~~ + """ + # use uri? + file_path: Path = uri_str_to_path(payload.text_document.uri) + try: + module_ast: ast.Module = await ast_provider.get_file_ast(file_path=file_path) + except SyntaxError: + return text_document_inlay_hint.InlayHintResult(hints=[]) + # mypy_file_revision: str = ast_provider.get_ast_revision(file_ast=mypy_file) + + # try: + # # cache.get_file_cache(file_path, mypy_file_revision) + # ... # TODO: get from cache + # except icache.CacheMissException: + + exported_members_names: list[str] | None = api.find_exported_members_names( + module_ast=module_ast + ) + module_members_with_access_type = api.get_module_members_with_access_type( + module_ast, exported_members_names, range_in_doc=payload.range + ) + + return text_document_inlay_hint.InlayHintResult( + hints=[ + text_document_inlay_hint.InlayHint( + position=common_types.Position( + line=stmt.lineno, character=stmt.col_offset + ), + label=( + "private" + if access_level == api.ModuleMemberAccessType.PRIVATE + else "public" + ), + kind=text_document_inlay_hint.InlayHintKind.TYPE, + padding_right=True, + ) + for stmt, access_level in module_members_with_access_type.items() + if access_level != api.ModuleMemberAccessType.UNKNOWN + ] + ) + + +def get_document_code_actions(): ... diff --git a/extensions/fine_python_module_exports/poetry.lock b/extensions/fine_python_module_exports/poetry.lock deleted file mode 100644 index 1e1d351..0000000 --- a/extensions/fine_python_module_exports/poetry.lock +++ /dev/null @@ -1,210 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "fine-python-ast" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_ast-0.1.0-py3-none-any.whl", hash = "sha256:3dcdcdc40ed89e0b90686f2ad5d358d8edba622a5de4c1f52f2f0787dcc4e07d"}, - {file = "fine_python_ast-0.1.0.tar.gz", hash = "sha256:ebc68aef7d0379f8771f610e436f6075b7c299a8895f1b9b7769fd038f95397e"}, -] - -[package.dependencies] -finecode_extension_api = "0.1.0" - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "finecode_extension_api-0.1.0-py3-none-any.whl", hash = "sha256:55d4448a1a2f7224c3fdf05879fa9782246c0a85dc1dfb17543374fd808c2b5b"}, - {file = "finecode_extension_api-0.1.0.tar.gz", hash = "sha256:dee16c180e4cd318f71bf7a94b6ae425667153f8fb62630ab60db9b034f45595"}, -] - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[[package]] -name = "pydantic" -version = "2.11.4" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb"}, - {file = "pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.33.2" -typing-extensions = ">=4.12.2" -typing-inspection = ">=0.4.0" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.33.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, - {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "typing-inspection" -version = "0.4.0" -description = "Runtime typing introspection tools" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"}, - {file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"}, -] - -[package.dependencies] -typing-extensions = ">=4.12.0" - -[metadata] -lock-version = "2.1" -python-versions = ">= 3.11, < 3.14" -content-hash = "c132c8ce7ed900d804a376b86b429d1ac6933dd438a845ab01df81adc2d1f5a1" diff --git a/extensions/fine_python_module_exports/pyproject.toml b/extensions/fine_python_module_exports/pyproject.toml index 6f4b139..0d163c5 100644 --- a/extensions/fine_python_module_exports/pyproject.toml +++ b/extensions/fine_python_module_exports/pyproject.toml @@ -1,13 +1,8 @@ [project] name = "fine-python-module-exports" -version = "0.1.0" +version = "0.2.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">= 3.11, < 3.14" -dependencies = ["finecode_extension_api==0.1.0", "fine_python_ast==0.1.0"] - - -[build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +dependencies = ["finecode_extension_api==0.3.*", "fine_python_ast==0.2.*"] diff --git a/extensions/fine_python_module_exports/setup.py b/extensions/fine_python_module_exports/setup.py new file mode 100644 index 0000000..ee123f8 --- /dev/null +++ b/extensions/fine_python_module_exports/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_module_exports", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/finecode_extension_api/finecode_extension_api/__init__.py b/extensions/fine_python_module_exports/tests/__init__.py similarity index 100% rename from finecode_extension_api/finecode_extension_api/__init__.py rename to extensions/fine_python_module_exports/tests/__init__.py diff --git a/extensions/fine_python_mypy/fine_python_mypy/action.py b/extensions/fine_python_mypy/fine_python_mypy/action.py index 51e4efa..790241e 100644 --- a/extensions/fine_python_mypy/fine_python_mypy/action.py +++ b/extensions/fine_python_mypy/fine_python_mypy/action.py @@ -1,6 +1,7 @@ # TODO: what to do with file manager? Mypy would need ability to check module text, # not only module file import asyncio +import dataclasses import hashlib import sys from pathlib import Path @@ -20,6 +21,7 @@ class DmypyFailedError(Exception): ... +@dataclasses.dataclass class MypyManyCodeActionConfig(code_action.ActionHandlerConfig): ... @@ -239,7 +241,7 @@ async def _run_dmypy(self, file_paths: list[Path], cwd: Path) -> str: self.logger.debug(f"run dmypy in {cwd}") status_file_path = self._get_status_file_path(dmypy_cwd=cwd) runner_python_executable = sys.executable - file_paths_str = " ".join([f"'{str(file_path)}'" for file_path in file_paths]) + file_paths_strs = [str(file_path) for file_path in file_paths] cmd_parts = [ f"{runner_python_executable}", "-m", @@ -248,7 +250,7 @@ async def _run_dmypy(self, file_paths: list[Path], cwd: Path) -> str: "run", "--", *self.DMYPY_ARGS, - f"{file_paths_str}", + *file_paths_strs, ] cmd = " ".join(cmd_parts) dmypy_run_process = await self.command_runner.run( diff --git a/extensions/fine_python_mypy/fine_python_mypy/ast_provider.py b/extensions/fine_python_mypy/fine_python_mypy/ast_provider.py index fe5d47e..d81fcfc 100644 --- a/extensions/fine_python_mypy/fine_python_mypy/ast_provider.py +++ b/extensions/fine_python_mypy/fine_python_mypy/ast_provider.py @@ -1,14 +1,14 @@ # import time from pathlib import Path -import mypy.nodes as mypy_nodes import mypy.build as mypy_build import mypy.modulefinder as modulefinder +import mypy.nodes as mypy_nodes import mypy.options as mypy_options -from finecode_extension_api.interfaces import ifilemanager, icache, ilogger - from fine_python_mypy import iast_provider +from finecode_extension_api.interfaces import icache, ifilemanager, ilogger + class MypySingleAstProvider(iast_provider.IMypySingleAstProvider): CACHE_KEY = "MypySingleAstProvider" diff --git a/extensions/fine_python_mypy/poetry.lock b/extensions/fine_python_mypy/poetry.lock deleted file mode 100644 index 35d7ae0..0000000 --- a/extensions/fine_python_mypy/poetry.lock +++ /dev/null @@ -1,260 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "finecode_extension_api-0.1.0-py3-none-any.whl", hash = "sha256:55d4448a1a2f7224c3fdf05879fa9782246c0a85dc1dfb17543374fd808c2b5b"}, - {file = "finecode_extension_api-0.1.0.tar.gz", hash = "sha256:dee16c180e4cd318f71bf7a94b6ae425667153f8fb62630ab60db9b034f45595"}, -] - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[[package]] -name = "mypy" -version = "1.15.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, - {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, - {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, - {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, - {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, - {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, - {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, - {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, - {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, - {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, - {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, - {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, - {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, - {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "pydantic" -version = "2.11.4" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb"}, - {file = "pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.33.2" -typing-extensions = ">=4.12.2" -typing-inspection = ">=0.4.0" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.33.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, - {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "typing-inspection" -version = "0.4.0" -description = "Runtime typing introspection tools" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"}, - {file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"}, -] - -[package.dependencies] -typing-extensions = ">=4.12.0" - -[metadata] -lock-version = "2.1" -python-versions = ">=3.11, < 3.14" -content-hash = "7aecd7613778317287f8fe4e4b589373d685ccbc3ca56a47fa8cef66ce1a5149" diff --git a/extensions/fine_python_mypy/pyproject.toml b/extensions/fine_python_mypy/pyproject.toml index 6a404c8..346bb29 100644 --- a/extensions/fine_python_mypy/pyproject.toml +++ b/extensions/fine_python_mypy/pyproject.toml @@ -1,13 +1,8 @@ [project] name = "fine-python-mypy" -version = "0.1.0" +version = "0.2.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">=3.11, < 3.14" -dependencies = ["finecode_extension_api==0.1.0", "mypy (>=1.15, <2.0)"] - - -[build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +dependencies = ["finecode_extension_api==0.3.*", "mypy (>=1.15, <2.0)"] diff --git a/extensions/fine_python_mypy/setup.py b/extensions/fine_python_mypy/setup.py new file mode 100644 index 0000000..1feff52 --- /dev/null +++ b/extensions/fine_python_mypy/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_mypy", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/extensions/fine_python_pip/.gitignore b/extensions/fine_python_pip/.gitignore new file mode 100644 index 0000000..d1dacee --- /dev/null +++ b/extensions/fine_python_pip/.gitignore @@ -0,0 +1,4 @@ +.venvs +src/*.egg-info +__pycache__ +finecode_config_dump/ diff --git a/extensions/fine_python_pip/README.md b/extensions/fine_python_pip/README.md new file mode 100644 index 0000000..d6ddb2d --- /dev/null +++ b/extensions/fine_python_pip/README.md @@ -0,0 +1 @@ +Run pip only as subprocess, not access its API programatically: https://pip.pypa.io/en/stable/user_guide/#using-pip-from-your-program diff --git a/extensions/fine_python_pip/pyproject.toml b/extensions/fine_python_pip/pyproject.toml new file mode 100644 index 0000000..6751b15 --- /dev/null +++ b/extensions/fine_python_pip/pyproject.toml @@ -0,0 +1,18 @@ +[project] +name = "fine-python-pip" +version = "0.1.0" +description = "" +authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] +readme = "README.md" +requires-python = ">=3.11, < 3.14" +dependencies = ["finecode_extension_api==0.3.*"] + +[dependency-groups] +dev_workspace = ["finecode==0.3.0"] +dev_no_runtime = ["finecode_dev_common_preset==0.2.*"] + +[tool.finecode] +presets = [{ source = "finecode_dev_common_preset" }] + +[tool.finecode.env.dev_no_runtime.dependencies] +finecode_dev_common_preset = { path = "../../finecode_dev_common_preset", editable = true } diff --git a/extensions/fine_python_pip/setup.py b/extensions/fine_python_pip/setup.py new file mode 100644 index 0000000..a7659bf --- /dev/null +++ b/extensions/fine_python_pip/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_pip", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/extensions/fine_python_pip/src/fine_python_pip/__init__.py b/extensions/fine_python_pip/src/fine_python_pip/__init__.py new file mode 100644 index 0000000..8439702 --- /dev/null +++ b/extensions/fine_python_pip/src/fine_python_pip/__init__.py @@ -0,0 +1,3 @@ +from .install_deps_in_env_handler import PipInstallDepsInEnvHandler + +__all__ = ["PipInstallDepsInEnvHandler"] diff --git a/extensions/fine_python_pip/src/fine_python_pip/install_deps_in_env_handler.py b/extensions/fine_python_pip/src/fine_python_pip/install_deps_in_env_handler.py new file mode 100644 index 0000000..e1800d8 --- /dev/null +++ b/extensions/fine_python_pip/src/fine_python_pip/install_deps_in_env_handler.py @@ -0,0 +1,106 @@ +import asyncio +import dataclasses +import pathlib + +from finecode_extension_api import code_action +from finecode_extension_api.actions import ( + install_deps_in_env as install_deps_in_env_action, +) +from finecode_extension_api.interfaces import icommandrunner, ilogger + + +@dataclasses.dataclass +class PipInstallDepsInEnvHandlerConfig(code_action.ActionHandlerConfig): + find_links: list[str] | None = None + + +class PipInstallDepsInEnvHandler( + code_action.ActionHandler[ + install_deps_in_env_action.InstallDepsInEnvAction, + PipInstallDepsInEnvHandlerConfig, + ] +): + def __init__( + self, + config: PipInstallDepsInEnvHandlerConfig, + command_runner: icommandrunner.ICommandRunner, + logger: ilogger.ILogger, + ) -> None: + self.config = config + self.command_runner = command_runner + self.logger = logger + + async def run( + self, + payload: install_deps_in_env_action.InstallDepsInEnvRunPayload, + run_context: install_deps_in_env_action.InstallDepsInEnvRunContext, + ) -> install_deps_in_env_action.InstallDepsInEnvRunResult: + env_name = payload.env_name + dependencies = payload.dependencies + venv_dir_path = payload.venv_dir_path + project_dir_path = payload.project_dir_path + python_executable = venv_dir_path / "bin" / "python" + + cmd = self._construct_pip_install_cmd( + python_executable=python_executable, dependencies=dependencies + ) + error = await self._run_pip_cmd( + cmd=cmd, env_name=env_name, project_dir_path=project_dir_path + ) + if error is not None: + errors = [error] + else: + errors = [] + + return install_deps_in_env_action.InstallDepsInEnvRunResult(errors=errors) + + def _construct_pip_install_cmd( + self, + python_executable: pathlib.Path, + dependencies: list[install_deps_in_env_action.Dependency], + ) -> str: + install_params: str = "" + + if self.config.find_links is not None: + for link in self.config.find_links: + install_params += f' --find-links="{link}" ' + + for dependency in dependencies: + if dependency.editable: + install_params += "-e " + + if "@ file://" in dependency.version_or_source: + # dependency is specified as ' @ file://' but pip CLI supports + # only 'file://' + start_idx_of_file_uri = dependency.version_or_source.index("file://") + # put in single quoutes to avoid problems in case of spaces in path + # because in CLI commands single dependencies are splitted by space + install_params += ( + f"'{dependency.version_or_source[start_idx_of_file_uri:]}' " + ) + else: + # put in single quoutes to avoid problems in case of spaces in version, + # because in CLI commands single dependencies are splitted by space + install_params += f"'{dependency.name}{dependency.version_or_source}' " + cmd = f"{python_executable} -m pip --disable-pip-version-check install {install_params}" + return cmd + + async def _run_pip_cmd( + self, cmd: str, env_name: str, project_dir_path: pathlib.Path + ) -> str | None: + process = await self.command_runner.run(cmd, cwd=project_dir_path) + await process.wait_for_end() + if process.get_exit_code() != 0: + process_stdout = process.get_output() + process_stderr = process.get_error_output() + logs = "" + if len(process_stdout) > 0 and len(process_stderr) > 0: + logs = f"stdout: {process_stdout}\nstderr: {process_stderr}" + elif len(process_stdout) > 0: + logs = process_stdout + else: + logs = process_stderr + + return f'Installation of dependencies "{cmd}" in env {env_name} from {project_dir_path} failed:\n{logs}' + + return None diff --git a/finecode_extension_api/finecode_extension_api/actions/__init__.py b/extensions/fine_python_pip/tests/__init__.py similarity index 100% rename from finecode_extension_api/finecode_extension_api/actions/__init__.py rename to extensions/fine_python_pip/tests/__init__.py diff --git a/extensions/fine_python_virtualenv/.gitignore b/extensions/fine_python_virtualenv/.gitignore new file mode 100644 index 0000000..250a6a2 --- /dev/null +++ b/extensions/fine_python_virtualenv/.gitignore @@ -0,0 +1,5 @@ +.venvs +build/ +src/*.egg-info/ +__pycache__ +finecode_config_dump/ diff --git a/finecode_extension_api/finecode_extension_api/actions/ide/__init__.py b/extensions/fine_python_virtualenv/README.md similarity index 100% rename from finecode_extension_api/finecode_extension_api/actions/ide/__init__.py rename to extensions/fine_python_virtualenv/README.md diff --git a/extensions/fine_python_virtualenv/pyproject.toml b/extensions/fine_python_virtualenv/pyproject.toml new file mode 100644 index 0000000..a0de105 --- /dev/null +++ b/extensions/fine_python_virtualenv/pyproject.toml @@ -0,0 +1,21 @@ +[project] +name = "fine-python-virtualenv" +version = "0.1.0" +description = "" +authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] +readme = "README.md" +requires-python = ">=3.11, < 3.14" +dependencies = [ + "finecode_extension_api==0.3.*", + "virtualenv (>=20.0.0,<21.0.0)", +] + +[dependency-groups] +dev_workspace = ["finecode==0.3.0"] +dev_no_runtime = ["finecode_dev_common_preset==0.2.*"] + +[tool.finecode] +presets = [{ source = "finecode_dev_common_preset" }] + +[tool.finecode.env.dev_no_runtime.dependencies] +finecode_dev_common_preset = { path = "../../finecode_dev_common_preset", editable = true } diff --git a/extensions/fine_python_virtualenv/setup.py b/extensions/fine_python_virtualenv/setup.py new file mode 100644 index 0000000..c8b9eda --- /dev/null +++ b/extensions/fine_python_virtualenv/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_virtualenv", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/extensions/fine_python_virtualenv/src/fine_python_virtualenv/__init__.py b/extensions/fine_python_virtualenv/src/fine_python_virtualenv/__init__.py new file mode 100644 index 0000000..bd3eaab --- /dev/null +++ b/extensions/fine_python_virtualenv/src/fine_python_virtualenv/__init__.py @@ -0,0 +1,4 @@ +from .prepare_envs_handler import VirtualenvPrepareEnvHandler +from .prepare_runners_handler import VirtualenvPrepareRunnersHandler + +__all__ = ["VirtualenvPrepareEnvHandler", "VirtualenvPrepareRunnersHandler"] diff --git a/extensions/fine_python_virtualenv/src/fine_python_virtualenv/prepare_envs_handler.py b/extensions/fine_python_virtualenv/src/fine_python_virtualenv/prepare_envs_handler.py new file mode 100644 index 0000000..a732bec --- /dev/null +++ b/extensions/fine_python_virtualenv/src/fine_python_virtualenv/prepare_envs_handler.py @@ -0,0 +1,54 @@ +import dataclasses + +import virtualenv + +from finecode_extension_api import code_action +from finecode_extension_api.actions import prepare_envs as prepare_envs_action +from finecode_extension_api.interfaces import ifilemanager, ilogger + + +@dataclasses.dataclass +class VirtualenvPrepareEnvHandlerConfig(code_action.ActionHandlerConfig): ... + + +class VirtualenvPrepareEnvHandler( + code_action.ActionHandler[ + prepare_envs_action.PrepareEnvsAction, VirtualenvPrepareEnvHandlerConfig + ] +): + def __init__( + self, + config: VirtualenvPrepareEnvHandlerConfig, + logger: ilogger.ILogger, + file_manager: ifilemanager.IFileManager, + ) -> None: + self.config = config + self.logger = logger + self.file_manager = file_manager + + async def run( + self, + payload: prepare_envs_action.PrepareEnvsRunPayload, + run_context: prepare_envs_action.PrepareEnvsRunContext, + ) -> prepare_envs_action.PrepareEnvsRunResult: + # create virtual envs + + # would it be faster parallel? + for env_info in payload.envs: + if payload.recreate and env_info.venv_dir_path.exists(): + self.logger.debug(f"Remove virtualenv dir {env_info.venv_dir_path}") + self.file_manager.remove_dir(env_info.venv_dir_path) + + self.logger.info(f"Creating virtualenv {env_info.venv_dir_path}") + if not env_info.venv_dir_path.exists(): + # TODO: '-p ' + virtualenv.cli_run( + [env_info.venv_dir_path.as_posix()], + options=None, + setup_logging=False, + env=None, + ) + else: + self.logger.info(f"Virtualenv in {env_info} exists already") + + return prepare_envs_action.PrepareEnvsRunResult(errors=[]) diff --git a/extensions/fine_python_virtualenv/src/fine_python_virtualenv/prepare_runners_handler.py b/extensions/fine_python_virtualenv/src/fine_python_virtualenv/prepare_runners_handler.py new file mode 100644 index 0000000..c546e91 --- /dev/null +++ b/extensions/fine_python_virtualenv/src/fine_python_virtualenv/prepare_runners_handler.py @@ -0,0 +1,55 @@ +import dataclasses + +import virtualenv + +from finecode_extension_api import code_action +from finecode_extension_api.actions import prepare_runners as prepare_runners_action +from finecode_extension_api.interfaces import ifilemanager, ilogger + + +@dataclasses.dataclass +class VirtualenvPrepareRunnersHandlerConfig(code_action.ActionHandlerConfig): ... + + +class VirtualenvPrepareRunnersHandler( + code_action.ActionHandler[ + prepare_runners_action.PrepareRunnersAction, + VirtualenvPrepareRunnersHandlerConfig, + ] +): + def __init__( + self, + config: VirtualenvPrepareRunnersHandlerConfig, + logger: ilogger.ILogger, + file_manager: ifilemanager.IFileManager, + ) -> None: + self.config = config + self.logger = logger + self.file_manager = file_manager + + async def run( + self, + payload: prepare_runners_action.PrepareRunnersRunPayload, + run_context: prepare_runners_action.PrepareRunnersRunContext, + ) -> prepare_runners_action.PrepareRunnersRunResult: + # create virtual envs + + # would it be faster parallel? + for env_info in payload.envs: + if payload.recreate and env_info.venv_dir_path.exists(): + self.logger.debug(f"Remove virtualenv dir {env_info.venv_dir_path}") + await self.file_manager.remove_dir(env_info.venv_dir_path) + + self.logger.info(f"Creating virtualenv {env_info.venv_dir_path}") + if not env_info.venv_dir_path.exists(): + # TODO: '-p ' + virtualenv.cli_run( + [env_info.venv_dir_path.as_posix()], + options=None, + setup_logging=False, + env=None, + ) + else: + self.logger.info(f"Virtualenv in {env_info} exists already") + + return prepare_runners_action.PrepareRunnersRunResult(errors=[]) diff --git a/finecode_extension_api/finecode_extension_api/interfaces/__init__.py b/extensions/fine_python_virtualenv/tests/__init__.py similarity index 100% rename from finecode_extension_api/finecode_extension_api/interfaces/__init__.py rename to extensions/fine_python_virtualenv/tests/__init__.py diff --git a/finecode.sh b/finecode.sh deleted file mode 100644 index 176acc2..0000000 --- a/finecode.sh +++ /dev/null @@ -1 +0,0 @@ -poetry run python \ No newline at end of file diff --git a/finecode_dev_common_preset/.gitignore b/finecode_dev_common_preset/.gitignore new file mode 100644 index 0000000..bf9e16a --- /dev/null +++ b/finecode_dev_common_preset/.gitignore @@ -0,0 +1,11 @@ +__pycache__ +.coverage +.pytest_cache +.mypy_cache +dist + +src/*.egg-info + +.venvs +finecode_config_dump/ +build/ \ No newline at end of file diff --git a/finecode_dev_common_preset/poetry.lock b/finecode_dev_common_preset/poetry.lock deleted file mode 100644 index 7c0956b..0000000 --- a/finecode_dev_common_preset/poetry.lock +++ /dev/null @@ -1,723 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "attrs" -version = "25.3.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, - {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, -] - -[package.extras] -benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] - -[[package]] -name = "black" -version = "25.1.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, - {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, - {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, - {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, - {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, - {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, - {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, - {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, - {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, - {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, - {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, - {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, - {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, - {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, - {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, - {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, - {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, - {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, - {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, - {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, - {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, - {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main"] -markers = "platform_system == \"Windows\"" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "fine-python-aksem" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -fine_python_module_exports = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_module_exports"} - -[package.source] -type = "git" -url = "https://github.com/Aksem/fine_python_aksem.git" -reference = "HEAD" -resolved_reference = "56ce22c3fb1228a6e85d1a8727a0fa74787608d9" - -[[package]] -name = "fine-python-ast" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "946844b2f151a7091664c407f7e24ce01442bee5" -subdirectory = "extensions/fine_python_ast" - -[[package]] -name = "fine-python-black" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -black = ">=25.1.0,<26.0.0" -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "946844b2f151a7091664c407f7e24ce01442bee5" -subdirectory = "extensions/fine_python_black" - -[[package]] -name = "fine-python-flake8" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -fine_python_ast = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_ast"} -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -flake8 = ">=7.1.2,<8.0.0" -types-flake8 = ">=7.1.0.20241020,<8.0.0.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "946844b2f151a7091664c407f7e24ce01442bee5" -subdirectory = "extensions/fine_python_flake8" - -[[package]] -name = "fine-python-format" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -fine_python_black = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_black"} -fine_python_isort = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_isort"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "946844b2f151a7091664c407f7e24ce01442bee5" -subdirectory = "presets/fine_python_format" - -[[package]] -name = "fine-python-isort" -version = "0.1.0" -description = "" -optional = false -python-versions = ">= 3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -isort = ">=5.13,<6" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "946844b2f151a7091664c407f7e24ce01442bee5" -subdirectory = "extensions/fine_python_isort" - -[[package]] -name = "fine-python-lint" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -fine_python_flake8 = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_flake8"} -fine_python_mypy = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_mypy"} -flake8-bugbear = ">=24.12.12,<25.0.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "946844b2f151a7091664c407f7e24ce01442bee5" -subdirectory = "presets/fine_python_lint" - -[[package]] -name = "fine-python-module-exports" -version = "0.1.0" -description = "" -optional = false -python-versions = ">= 3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -fine_python_ast = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_ast"} -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "946844b2f151a7091664c407f7e24ce01442bee5" -subdirectory = "extensions/fine_python_module_exports" - -[[package]] -name = "fine-python-mypy" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -mypy = ">=1.15,<2.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "946844b2f151a7091664c407f7e24ce01442bee5" -subdirectory = "extensions/fine_python_mypy" - -[[package]] -name = "fine-python-recommended" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -fine_python_format = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_format"} -fine_python_lint = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_lint"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "946844b2f151a7091664c407f7e24ce01442bee5" -subdirectory = "presets/fine_python_recommended" - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["main"] -files = [] -develop = false - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "946844b2f151a7091664c407f7e24ce01442bee5" -subdirectory = "finecode_extension_api" - -[[package]] -name = "flake8" -version = "7.2.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343"}, - {file = "flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.13.0,<2.14.0" -pyflakes = ">=3.3.0,<3.4.0" - -[[package]] -name = "flake8-bugbear" -version = "24.12.12" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -optional = false -python-versions = ">=3.8.1" -groups = ["main"] -files = [ - {file = "flake8_bugbear-24.12.12-py3-none-any.whl", hash = "sha256:1b6967436f65ca22a42e5373aaa6f2d87966ade9aa38d4baf2a1be550767545e"}, - {file = "flake8_bugbear-24.12.12.tar.gz", hash = "sha256:46273cef0a6b6ff48ca2d69e472f41420a42a46e24b2a8972e4f0d6733d12a64"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -flake8 = ">=6.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mypy" -version = "1.15.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, - {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, - {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, - {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, - {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, - {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, - {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, - {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, - {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, - {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, - {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, - {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, - {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, - {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.3.7" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94"}, - {file = "platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] - -[[package]] -name = "pycodestyle" -version = "2.13.0" -description = "Python style guide checker" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9"}, - {file = "pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae"}, -] - -[[package]] -name = "pydantic" -version = "2.11.4" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic-2.11.4-py3-none-any.whl", hash = "sha256:d9615eaa9ac5a063471da949c8fc16376a84afb5024688b3ff885693506764eb"}, - {file = "pydantic-2.11.4.tar.gz", hash = "sha256:32738d19d63a226a52eed76645a98ee07c1f410ee41d93b4afbfa85ed8111c2d"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.33.2" -typing-extensions = ">=4.12.2" -typing-inspection = ">=0.4.0" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.33.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, - {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, - {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, - {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, - {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, - {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, - {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, - {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, - {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, - {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, - {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, - {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, - {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, - {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, - {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, - {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, - {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, - {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, - {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, - {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, - {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, - {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, - {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, - {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pyflakes" -version = "3.3.2" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a"}, - {file = "pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b"}, -] - -[[package]] -name = "types-flake8" -version = "7.2.0.20250330" -description = "Typing stubs for flake8" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "types_flake8-7.2.0.20250330-py3-none-any.whl", hash = "sha256:af31590a269586309b80a439c94e59359e139e17475a8fc8d3c426ab01a40547"}, - {file = "types_flake8-7.2.0.20250330.tar.gz", hash = "sha256:481e5c914a26fabd23e85704ad055f2716f9238740bfe6fe77259c2533cb970c"}, -] - -[package.dependencies] -types-pyflakes = "*" - -[[package]] -name = "types-pyflakes" -version = "3.3.2.20250429" -description = "Typing stubs for pyflakes" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "types_pyflakes-3.3.2.20250429-py3-none-any.whl", hash = "sha256:f9ccc1968ddd1a18232c1e66cfcce8a9e8f4b2b85fbbf682bf87148a2b2d58a0"}, - {file = "types_pyflakes-3.3.2.20250429.tar.gz", hash = "sha256:a81b0ee91e34d143f655d366bd4002730f0e342a5aa338779d2f995515ce1c5c"}, -] - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "typing-inspection" -version = "0.4.0" -description = "Runtime typing introspection tools" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"}, - {file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"}, -] - -[package.dependencies] -typing-extensions = ">=4.12.0" - -[metadata] -lock-version = "2.1" -python-versions = ">=3.11, < 3.14" -content-hash = "21456805d44cb3d018f182a4d345d7e8165871f4ee1f7c41b70e755cbd0a3a7f" diff --git a/finecode_dev_common_preset/pyproject.toml b/finecode_dev_common_preset/pyproject.toml index cd59846..7424a97 100644 --- a/finecode_dev_common_preset/pyproject.toml +++ b/finecode_dev_common_preset/pyproject.toml @@ -1,18 +1,14 @@ [project] name = "finecode-dev-common-preset" -version = "0.1.0" +version = "0.2.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">=3.11, < 3.14" dependencies = [ "fine_python_aksem @ git+https://github.com/Aksem/fine_python_aksem.git", - "fine_python_recommended @ git+https://github.com/finecode-dev/finecode.git#subdirectory=presets/fine_python_recommended", + "fine_python_recommended==0.2.*", ] -[tool.poetry] -packages = [{ include = "finecode_dev_common_preset", from = "src" }] - -[build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +[tool.setuptools.package-data] +finecode_dev_common_preset = ["preset.toml"] diff --git a/finecode_dev_common_preset/src/finecode_dev_common_preset/preset.toml b/finecode_dev_common_preset/src/finecode_dev_common_preset/preset.toml index 545d1a0..3790b5f 100644 --- a/finecode_dev_common_preset/src/finecode_dev_common_preset/preset.toml +++ b/finecode_dev_common_preset/src/finecode_dev_common_preset/preset.toml @@ -4,5 +4,12 @@ presets = [ { source = "fine_python_aksem" }, ] -[tool.finecode.action_handler.black.config] -preview = true +[[tool.finecode.action_handler]] +source = "fine_python_black.BlackFormatHandler" +config.preview = true + +# currently, all packages in finecode repository are pure python packages, reuse +# setuptools build in all of them +[build-system] +requires = ["setuptools>=64", "setuptools-scm>=8"] +build-backend = "setuptools.build_meta" diff --git a/finecode_extension_api/.gitignore b/finecode_extension_api/.gitignore new file mode 100644 index 0000000..81441a3 --- /dev/null +++ b/finecode_extension_api/.gitignore @@ -0,0 +1,4 @@ +.venvs/ +*.egg-info +build/ +finecode_config_dump/ \ No newline at end of file diff --git a/finecode_extension_api/finecode_extension_api/common_types.py b/finecode_extension_api/finecode_extension_api/common_types.py deleted file mode 100644 index 4fd0923..0000000 --- a/finecode_extension_api/finecode_extension_api/common_types.py +++ /dev/null @@ -1,22 +0,0 @@ -from finecode_extension_api.code_action import BaseModel - - -class Position(BaseModel): - line: int - character: int - - -class Range(BaseModel): - start: Position - end: Position - - -class TextDocumentIdentifier(BaseModel): - uri: str - - -class TextDocumentItem(BaseModel): - uri: str - language_id: str - version: int - text: str diff --git a/finecode_extension_api/poetry.lock b/finecode_extension_api/poetry.lock deleted file mode 100644 index a6c4ecc..0000000 --- a/finecode_extension_api/poetry.lock +++ /dev/null @@ -1,902 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "attrs" -version = "25.3.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, - {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, -] - -[package.extras] -benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] - -[[package]] -name = "black" -version = "25.1.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, - {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, - {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, - {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, - {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, - {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, - {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, - {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, - {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, - {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, - {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, - {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, - {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, - {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, - {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, - {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, - {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, - {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, - {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, - {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, - {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, - {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "cattrs" -version = "24.1.3" -description = "Composable complex class support for attrs and dataclasses." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "cattrs-24.1.3-py3-none-any.whl", hash = "sha256:adf957dddd26840f27ffbd060a6c4dd3b2192c5b7c2c0525ef1bd8131d8a83f5"}, - {file = "cattrs-24.1.3.tar.gz", hash = "sha256:981a6ef05875b5bb0c7fb68885546186d306f10f0f6718fe9b96c226e68821ff"}, -] - -[package.dependencies] -attrs = ">=23.1.0" - -[package.extras] -bson = ["pymongo (>=4.4.0)"] -cbor2 = ["cbor2 (>=5.4.6)"] -msgpack = ["msgpack (>=1.0.5)"] -msgspec = ["msgspec (>=0.18.5) ; implementation_name == \"cpython\""] -orjson = ["orjson (>=3.9.2) ; implementation_name == \"cpython\""] -pyyaml = ["pyyaml (>=6.0)"] -tomlkit = ["tomlkit (>=0.11.8)"] -ujson = ["ujson (>=5.7.0)"] - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["dev"] -markers = "sys_platform == \"win32\" or platform_system == \"Windows\"" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "fine-python-aksem" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_module_exports = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_module_exports"} - -[package.source] -type = "git" -url = "https://github.com/Aksem/fine_python_aksem.git" -reference = "HEAD" -resolved_reference = "56ce22c3fb1228a6e85d1a8727a0fa74787608d9" - -[[package]] -name = "fine-python-ast" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "51fa7a9bb80d21455dc89c8b1c6e7049177363da" -subdirectory = "extensions/fine_python_ast" - -[[package]] -name = "fine-python-black" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -black = ">=25.1.0,<26.0.0" -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "51fa7a9bb80d21455dc89c8b1c6e7049177363da" -subdirectory = "extensions/fine_python_black" - -[[package]] -name = "fine-python-flake8" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_ast = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_ast"} -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -flake8 = ">=7.1.2,<8.0.0" -types-flake8 = ">=7.1.0.20241020,<8.0.0.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "51fa7a9bb80d21455dc89c8b1c6e7049177363da" -subdirectory = "extensions/fine_python_flake8" - -[[package]] -name = "fine-python-format" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_black = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_black"} -fine_python_isort = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_isort"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "51fa7a9bb80d21455dc89c8b1c6e7049177363da" -subdirectory = "presets/fine_python_format" - -[[package]] -name = "fine-python-isort" -version = "0.1.0" -description = "" -optional = false -python-versions = ">= 3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -isort = ">=5.13,<6" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "51fa7a9bb80d21455dc89c8b1c6e7049177363da" -subdirectory = "extensions/fine_python_isort" - -[[package]] -name = "fine-python-lint" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_flake8 = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_flake8"} -fine_python_mypy = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_mypy"} -flake8-bugbear = ">=24.12.12,<25.0.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "51fa7a9bb80d21455dc89c8b1c6e7049177363da" -subdirectory = "presets/fine_python_lint" - -[[package]] -name = "fine-python-module-exports" -version = "0.1.0" -description = "" -optional = false -python-versions = ">= 3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_ast = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_ast"} -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "51fa7a9bb80d21455dc89c8b1c6e7049177363da" -subdirectory = "extensions/fine_python_module_exports" - -[[package]] -name = "fine-python-mypy" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -mypy = ">=1.15,<2.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "51fa7a9bb80d21455dc89c8b1c6e7049177363da" -subdirectory = "extensions/fine_python_mypy" - -[[package]] -name = "fine-python-recommended" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_format = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_format"} -fine_python_lint = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_lint"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "51fa7a9bb80d21455dc89c8b1c6e7049177363da" -subdirectory = "presets/fine_python_recommended" - -[[package]] -name = "finecode" -version = "0.2.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -click = "==8.1.*" -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -loguru = "==0.7.*" -ordered-set = "==4.1.*" -platformdirs = "==4.3.*" -pydantic = "==2.10.*" -pygls = "2.0.0-a2" -tomlkit = "==0.11.*" -watchdog = "==4.0.*" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "51fa7a9bb80d21455dc89c8b1c6e7049177363da" - -[[package]] -name = "finecode-dev-common-preset" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = true - -[package.dependencies] -fine_python_aksem = {git = "https://github.com/Aksem/fine_python_aksem.git"} -fine_python_recommended = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_recommended"} - -[package.source] -type = "directory" -url = "../finecode_dev_common_preset" - -[[package]] -name = "flake8" -version = "7.2.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343"}, - {file = "flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.13.0,<2.14.0" -pyflakes = ">=3.3.0,<3.4.0" - -[[package]] -name = "flake8-bugbear" -version = "24.12.12" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -optional = false -python-versions = ">=3.8.1" -groups = ["dev"] -files = [ - {file = "flake8_bugbear-24.12.12-py3-none-any.whl", hash = "sha256:1b6967436f65ca22a42e5373aaa6f2d87966ade9aa38d4baf2a1be550767545e"}, - {file = "flake8_bugbear-24.12.12.tar.gz", hash = "sha256:46273cef0a6b6ff48ca2d69e472f41420a42a46e24b2a8972e4f0d6733d12a64"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -flake8 = ">=6.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -groups = ["dev"] -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "loguru" -version = "0.7.3" -description = "Python logging made (stupidly) simple" -optional = false -python-versions = "<4.0,>=3.5" -groups = ["dev"] -files = [ - {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, - {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==v0.910) ; python_version < \"3.6\"", "mypy (==v0.971) ; python_version == \"3.6\"", "mypy (==v1.13.0) ; python_version >= \"3.8\"", "mypy (==v1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] - -[[package]] -name = "lsprotocol" -version = "2024.0.0b1" -description = "Python types for Language Server Protocol." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "lsprotocol-2024.0.0b1-py3-none-any.whl", hash = "sha256:93785050ac155ae2be16b1ebfbd74c214feb3d3ef77b10399ce941e5ccef6ebd"}, - {file = "lsprotocol-2024.0.0b1.tar.gz", hash = "sha256:d3667fb70894d361aa6c495c5c8a1b2e6a44be65ff84c21a9cbb67ebfb4830fd"}, -] - -[package.dependencies] -attrs = ">=21.3.0" -cattrs = "!=23.2.1" - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mypy" -version = "1.15.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, - {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, - {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, - {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, - {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, - {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, - {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, - {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, - {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, - {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, - {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, - {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, - {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, - {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "ordered-set" -version = "4.1.0" -description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, - {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"}, -] - -[package.extras] -dev = ["black", "mypy", "pytest"] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.3.7" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94"}, - {file = "platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] - -[[package]] -name = "pycodestyle" -version = "2.13.0" -description = "Python style guide checker" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9"}, - {file = "pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae"}, -] - -[[package]] -name = "pydantic" -version = "2.10.6" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, - {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.27.2" -typing-extensions = ">=4.12.2" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.27.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, - {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pyflakes" -version = "3.3.2" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a"}, - {file = "pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b"}, -] - -[[package]] -name = "pygls" -version = "2.0.0a2" -description = "A pythonic generic language server (pronounced like 'pie glass')" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pygls-2.0.0a2-py3-none-any.whl", hash = "sha256:b202369321409343aa6440d73111d9fa0c22e580466ff1c7696b8358bb91f243"}, - {file = "pygls-2.0.0a2.tar.gz", hash = "sha256:03e00634ed8d989918268aaa4b4a0c3ab857ea2d4ee94514a52efa5ddd6d5d9f"}, -] - -[package.dependencies] -cattrs = ">=23.1.2" -lsprotocol = "2024.0.0b1" - -[package.extras] -ws = ["websockets (>=13.0)"] - -[[package]] -name = "tomlkit" -version = "0.11.8" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, - {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, -] - -[[package]] -name = "types-flake8" -version = "7.2.0.20250330" -description = "Typing stubs for flake8" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "types_flake8-7.2.0.20250330-py3-none-any.whl", hash = "sha256:af31590a269586309b80a439c94e59359e139e17475a8fc8d3c426ab01a40547"}, - {file = "types_flake8-7.2.0.20250330.tar.gz", hash = "sha256:481e5c914a26fabd23e85704ad055f2716f9238740bfe6fe77259c2533cb970c"}, -] - -[package.dependencies] -types-pyflakes = "*" - -[[package]] -name = "types-pyflakes" -version = "3.3.2.20250429" -description = "Typing stubs for pyflakes" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "types_pyflakes-3.3.2.20250429-py3-none-any.whl", hash = "sha256:f9ccc1968ddd1a18232c1e66cfcce8a9e8f4b2b85fbbf682bf87148a2b2d58a0"}, - {file = "types_pyflakes-3.3.2.20250429.tar.gz", hash = "sha256:a81b0ee91e34d143f655d366bd4002730f0e342a5aa338779d2f995515ce1c5c"}, -] - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "watchdog" -version = "4.0.2" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8"}, - {file = "watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19"}, - {file = "watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b"}, - {file = "watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c"}, - {file = "watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[[package]] -name = "win32-setctime" -version = "1.2.0" -description = "A small Python utility to set file creation time on Windows" -optional = false -python-versions = ">=3.5" -groups = ["dev"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, - {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, -] - -[package.extras] -dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] - -[metadata] -lock-version = "2.1" -python-versions = ">=3.11, < 3.14" -content-hash = "ca4aedcc1b712706890117d8c59ed135f4fc11ee925c6237e126f8d891ee959c" diff --git a/finecode_extension_api/pyproject.toml b/finecode_extension_api/pyproject.toml index 47f79bc..900c6fc 100644 --- a/finecode_extension_api/pyproject.toml +++ b/finecode_extension_api/pyproject.toml @@ -1,22 +1,18 @@ [project] name = "finecode-extension-api" -version = "0.1.0" +version = "0.3.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">=3.11, < 3.14" -dependencies = [ - "pydantic (>=2.10.6,<3.0.0)", - "typing-extensions (>=4.12.2,<5.0.0)", -] +dependencies = ["typing-extensions (>=4.12.2,<5.0.0)"] -[build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" - -[tool.poetry.group.dev.dependencies] -finecode = { git = "https://github.com/finecode-dev/finecode.git" } -finecode_dev_common_preset = { path = "../finecode_dev_common_preset", develop = true } +[dependency-groups] +dev_workspace = ["finecode==0.3.0"] +dev_no_runtime = ["finecode_dev_common_preset==0.2.*"] [tool.finecode] presets = [{ source = "finecode_dev_common_preset" }] + +[tool.finecode.env.dev_no_runtime.dependencies] +finecode_dev_common_preset = { path = "../finecode_dev_common_preset", editable = true } diff --git a/finecode_extension_api/setup.py b/finecode_extension_api/setup.py new file mode 100644 index 0000000..195afdf --- /dev/null +++ b/finecode_extension_api/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="finecode_extension_api", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/src/finecode/extension_runner/__init__.py b/finecode_extension_api/src/finecode_extension_api/__init__.py similarity index 100% rename from src/finecode/extension_runner/__init__.py rename to finecode_extension_api/src/finecode_extension_api/__init__.py diff --git a/src/finecode/extension_runner/impls/__init__.py b/finecode_extension_api/src/finecode_extension_api/actions/__init__.py similarity index 100% rename from src/finecode/extension_runner/impls/__init__.py rename to finecode_extension_api/src/finecode_extension_api/actions/__init__.py diff --git a/finecode_extension_api/finecode_extension_api/py.typed b/finecode_extension_api/src/finecode_extension_api/actions/check_formatting.py similarity index 100% rename from finecode_extension_api/finecode_extension_api/py.typed rename to finecode_extension_api/src/finecode_extension_api/actions/check_formatting.py diff --git a/finecode_extension_api/src/finecode_extension_api/actions/dump_config.py b/finecode_extension_api/src/finecode_extension_api/actions/dump_config.py new file mode 100644 index 0000000..4cfa428 --- /dev/null +++ b/finecode_extension_api/src/finecode_extension_api/actions/dump_config.py @@ -0,0 +1,57 @@ +import dataclasses +import pathlib +import pprint +import sys +import typing + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + +from finecode_extension_api import code_action, textstyler + + +@dataclasses.dataclass +class DumpConfigRunPayload(code_action.RunActionPayload): + # `source_file_path` is not for reading, config is already read and its content is + # in `project_raw_config`, but for providing config path to allow for example to + # resolve relative pathes in project config + source_file_path: pathlib.Path + project_raw_config: dict[str, typing.Any] + target_file_path: pathlib.Path + + +class DumpConfigRunContext(code_action.RunActionContext): + def __init__( + self, + run_id: int, + ) -> None: + super().__init__(run_id=run_id) + + self.raw_config_dump: dict[str, typing.Any] = {} + + async def init(self, initial_payload: DumpConfigRunPayload) -> None: + self.raw_config_dump = initial_payload.project_raw_config + + +@dataclasses.dataclass +class DumpConfigRunResult(code_action.RunActionResult): + config_dump: dict[str, typing.Any] + + @override + def update(self, other: code_action.RunActionResult) -> None: + if not isinstance(other, DumpConfigRunResult): + return + + self.config_dump = other.config_dump + + def to_text(self) -> str | textstyler.StyledText: + formatted_dump_str = pprint.pformat(self.config_dump) + return formatted_dump_str + + +class DumpConfigAction(code_action.Action): + PAYLOAD_TYPE = DumpConfigRunPayload + RUN_CONTEXT_TYPE = DumpConfigRunContext + RESULT_TYPE = DumpConfigRunResult diff --git a/finecode_extension_api/finecode_extension_api/actions/format.py b/finecode_extension_api/src/finecode_extension_api/actions/format.py similarity index 92% rename from finecode_extension_api/finecode_extension_api/actions/format.py rename to finecode_extension_api/src/finecode_extension_api/actions/format.py index c5da7cc..fa251f0 100644 --- a/finecode_extension_api/finecode_extension_api/actions/format.py +++ b/finecode_extension_api/src/finecode_extension_api/actions/format.py @@ -1,3 +1,4 @@ +import dataclasses import sys from pathlib import Path from typing import NamedTuple @@ -12,6 +13,7 @@ from finecode_extension_api import code_action, textstyler +@dataclasses.dataclass class FormatRunPayload(code_action.RunActionPayload): file_paths: list[Path] save: bool @@ -42,12 +44,14 @@ async def init(self, initial_payload: FormatRunPayload) -> None: ) -class FormatRunFileResult(code_action.RunActionResult): +@dataclasses.dataclass +class FormatRunFileResult: changed: bool # changed code or empty string if code was not changed code: str +@dataclasses.dataclass class FormatRunResult(code_action.RunActionResult): result_by_file_path: dict[Path, FormatRunFileResult] @@ -79,11 +83,13 @@ def to_text(self) -> str | textstyler.StyledText: return text -type FormatAction = code_action.Action[ - FormatRunPayload, FormatRunContext, FormatRunResult -] +class FormatAction(code_action.Action): + PAYLOAD_TYPE = FormatRunPayload + RUN_CONTEXT_TYPE = FormatRunContext + RESULT_TYPE = FormatRunResult +@dataclasses.dataclass class SaveFormatHandlerConfig(code_action.ActionHandlerConfig): ... diff --git a/src/finecode/workspace_manager/__init__.py b/finecode_extension_api/src/finecode_extension_api/actions/ide/__init__.py similarity index 100% rename from src/finecode/workspace_manager/__init__.py rename to finecode_extension_api/src/finecode_extension_api/actions/ide/__init__.py diff --git a/finecode_extension_api/finecode_extension_api/actions/ide/text_document_code_action.py b/finecode_extension_api/src/finecode_extension_api/actions/ide/text_document_code_action.py similarity index 85% rename from finecode_extension_api/finecode_extension_api/actions/ide/text_document_code_action.py rename to finecode_extension_api/src/finecode_extension_api/actions/ide/text_document_code_action.py index 84bf6cb..16e9bfd 100644 --- a/finecode_extension_api/finecode_extension_api/actions/ide/text_document_code_action.py +++ b/finecode_extension_api/src/finecode_extension_api/actions/ide/text_document_code_action.py @@ -1,8 +1,10 @@ +import dataclasses import enum from finecode_extension_api import code_action, common_types +@dataclasses.dataclass class CodeActionPayload(code_action.RunActionPayload): text_document: common_types.TextDocumentIdentifier range: common_types.Range @@ -27,10 +29,12 @@ class CodeActionTriggerKind(enum.IntEnum): AUTOMATIC = 2 -class Diagnostic(code_action.BaseModel): ... +@dataclasses.dataclass +class Diagnostic: ... -class CodeActionContext(code_action.BaseModel): +@dataclasses.dataclass +class CodeActionContext: diagnostics: list[Diagnostic] only: CodeActionKind | None trigger_kind: CodeActionTriggerKind diff --git a/finecode_extension_api/finecode_extension_api/actions/ide/text_document_inlay_hint.py b/finecode_extension_api/src/finecode_extension_api/actions/ide/text_document_inlay_hint.py similarity index 68% rename from finecode_extension_api/finecode_extension_api/actions/ide/text_document_inlay_hint.py rename to finecode_extension_api/src/finecode_extension_api/actions/ide/text_document_inlay_hint.py index b2523d7..44fb9f5 100644 --- a/finecode_extension_api/finecode_extension_api/actions/ide/text_document_inlay_hint.py +++ b/finecode_extension_api/src/finecode_extension_api/actions/ide/text_document_inlay_hint.py @@ -1,8 +1,10 @@ +import dataclasses import enum from finecode_extension_api import code_action, common_types +@dataclasses.dataclass class InlayHintPayload(code_action.RunActionPayload): text_document: common_types.TextDocumentIdentifier range: common_types.Range @@ -13,7 +15,8 @@ class InlayHintKind(enum.IntEnum): PARAM = 2 -class InlayHint(code_action.BaseModel): +@dataclasses.dataclass +class InlayHint: position: common_types.Position label: str kind: InlayHintKind @@ -21,10 +24,11 @@ class InlayHint(code_action.BaseModel): padding_right: bool = False +@dataclasses.dataclass class InlayHintResult(code_action.RunActionResult): hints: list[InlayHint] | None -type TextDocumentInlayHintAction = code_action.Action[ - InlayHintPayload, code_action.RunActionContext, InlayHintResult -] +class TextDocumentInlayHintAction(code_action.Action): + PAYLOAD_TYPE = InlayHintPayload + RESULT_TYPE = InlayHintResult diff --git a/finecode_extension_api/src/finecode_extension_api/actions/install_deps_in_env.py b/finecode_extension_api/src/finecode_extension_api/actions/install_deps_in_env.py new file mode 100644 index 0000000..e8de2f8 --- /dev/null +++ b/finecode_extension_api/src/finecode_extension_api/actions/install_deps_in_env.py @@ -0,0 +1,60 @@ +import dataclasses +import pathlib +import sys + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + +from finecode_extension_api import code_action, textstyler + + +@dataclasses.dataclass +class Dependency: + name: str + version_or_source: str + editable: bool = False + + +@dataclasses.dataclass +class InstallDepsInEnvRunPayload(code_action.RunActionPayload): + env_name: str + venv_dir_path: pathlib.Path + project_dir_path: pathlib.Path + dependencies: list[Dependency] + + +class InstallDepsInEnvRunContext(code_action.RunActionContext): + def __init__( + self, + run_id: int, + ) -> None: + super().__init__(run_id=run_id) + + +@dataclasses.dataclass +class InstallDepsInEnvRunResult(code_action.RunActionResult): + errors: list[str] + + @override + def update(self, other: code_action.RunActionResult) -> None: + if not isinstance(other, InstallDepsInEnvRunResult): + return + self.errors += other.errors + + def to_text(self) -> str | textstyler.StyledText: + return "\n".join(self.errors) + + @property + def return_code(self) -> code_action.RunReturnCode: + if len(self.errors) == 0: + return code_action.RunReturnCode.SUCCESS + else: + return code_action.RunReturnCode.ERROR + + +class InstallDepsInEnvAction(code_action.Action): + PAYLOAD_TYPE = InstallDepsInEnvRunPayload + RUN_CONTEXT_TYPE = InstallDepsInEnvRunContext + RESULT_TYPE = InstallDepsInEnvRunResult diff --git a/finecode_extension_api/finecode_extension_api/actions/lint.py b/finecode_extension_api/src/finecode_extension_api/actions/lint.py similarity index 89% rename from finecode_extension_api/finecode_extension_api/actions/lint.py rename to finecode_extension_api/src/finecode_extension_api/actions/lint.py index 34046d0..39f5510 100644 --- a/finecode_extension_api/finecode_extension_api/actions/lint.py +++ b/finecode_extension_api/src/finecode_extension_api/actions/lint.py @@ -1,16 +1,19 @@ import collections.abc +import dataclasses import enum from pathlib import Path from finecode_extension_api import code_action, textstyler -class Position(code_action.BaseModel): +@dataclasses.dataclass +class Position: line: int character: int -class Range(code_action.BaseModel): +@dataclasses.dataclass +class Range: start: Position end: Position @@ -23,7 +26,8 @@ class LintMessageSeverity(enum.IntEnum): HINT = 4 -class LintMessage(code_action.BaseModel): +@dataclasses.dataclass +class LintMessage: range: Range message: str code: str | None = None @@ -32,6 +36,7 @@ class LintMessage(code_action.BaseModel): severity: LintMessageSeverity | None = None +@dataclasses.dataclass class LintRunPayload(code_action.RunActionPayload, collections.abc.AsyncIterable): file_paths: list[Path] @@ -39,6 +44,7 @@ def __aiter__(self) -> collections.abc.AsyncIterator[Path]: return LintRunPayloadIterator(self) +@dataclasses.dataclass class LintRunPayloadIterator(collections.abc.AsyncIterator): def __init__(self, lint_run_payload: LintRunPayload): self.lint_run_payload = lint_run_payload @@ -54,6 +60,7 @@ async def __anext__(self) -> Path: return self.lint_run_payload.file_paths[self.current_file_path_index - 1] +@dataclasses.dataclass class LintRunResult(code_action.RunActionResult): # messages is a dict to support messages for multiple files because it could be the # case that linter checks given file and its dependencies. @@ -100,6 +107,7 @@ def return_code(self) -> code_action.RunReturnCode: return code_action.RunReturnCode.SUCCESS -type LintAction = code_action.Action[ - LintRunPayload, code_action.RunActionWithPartialResultsContext, LintRunResult -] +class LintAction(code_action.Action): + PAYLOAD_TYPE = LintRunPayload + RUN_CONTEXT_TYPE = code_action.RunActionWithPartialResultsContext + RESULT_TYPE = LintRunResult diff --git a/finecode_extension_api/src/finecode_extension_api/actions/prepare_envs.py b/finecode_extension_api/src/finecode_extension_api/actions/prepare_envs.py new file mode 100644 index 0000000..ff7b7e2 --- /dev/null +++ b/finecode_extension_api/src/finecode_extension_api/actions/prepare_envs.py @@ -0,0 +1,85 @@ +import dataclasses +import pathlib +import sys +import typing + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + +from finecode_extension_api import code_action, textstyler + + +@dataclasses.dataclass +class EnvInfo: + name: str + venv_dir_path: pathlib.Path + project_def_path: pathlib.Path + + +@dataclasses.dataclass +class PrepareEnvsRunPayload(code_action.RunActionPayload): + envs: list[EnvInfo] + # remove old env and create a new one from scratch even if the current one is valid. + # Useful for example if you changed something in venv manually and want to revert + # changes (just by running prepare it would be not solved because version of the + # packages are the same and they are already installed) + recreate: bool = False + + +class PrepareEnvsRunContext(code_action.RunActionContext): + def __init__( + self, + run_id: int, + ) -> None: + super().__init__(run_id=run_id) + + # project def pathes are stored also in context, because prepare envs can run + # tools like pip which expected 'normalized' project definition(=without + # additional features which finecode provides). So the usual workflow looks like + # normalizing(dumping) configuration first and then use dumped config for + # further handlers. + self.project_def_path_by_venv_dir_path: dict[pathlib.Path, pathlib.Path] = {} + # to avoid multiple writing and reading files in each action handler, save + # modified project definition here. It also can be used as extension point if + # for example additional dependencies should be installed by adding handler + # which inserts them into project definition instead of modying `install_deps` + # handler + self.project_def_by_venv_dir_path: dict[pathlib.Path, dict[str, typing.Any]] = ( + {} + ) + + async def init(self, initial_payload: PrepareEnvsRunPayload) -> None: + for env_info in initial_payload.envs: + self.project_def_path_by_venv_dir_path[env_info.venv_dir_path] = ( + env_info.project_def_path + ) + + +@dataclasses.dataclass +class PrepareEnvsRunResult(code_action.RunActionResult): + # `PrepareEnvs` action is general, so make result general as well + errors: list[str] + + @override + def update(self, other: code_action.RunActionResult) -> None: + if not isinstance(other, PrepareEnvsRunResult): + return + self.errors += other.errors + + def to_text(self) -> str | textstyler.StyledText: + return "\n".join(self.errors) + + @property + def return_code(self) -> code_action.RunReturnCode: + if len(self.errors) == 0: + return code_action.RunReturnCode.SUCCESS + else: + return code_action.RunReturnCode.ERROR + + +class PrepareEnvsAction(code_action.Action): + PAYLOAD_TYPE = PrepareEnvsRunPayload + RUN_CONTEXT_TYPE = PrepareEnvsRunContext + RESULT_TYPE = PrepareEnvsRunResult diff --git a/finecode_extension_api/src/finecode_extension_api/actions/prepare_runners.py b/finecode_extension_api/src/finecode_extension_api/actions/prepare_runners.py new file mode 100644 index 0000000..ec1a9fc --- /dev/null +++ b/finecode_extension_api/src/finecode_extension_api/actions/prepare_runners.py @@ -0,0 +1,85 @@ +import dataclasses +import pathlib +import sys +import typing + +if sys.version_info >= (3, 12): + from typing import override +else: + from typing_extensions import override + +from finecode_extension_api import code_action, textstyler + + +@dataclasses.dataclass +class EnvInfo: + name: str + venv_dir_path: pathlib.Path + project_def_path: pathlib.Path + + +@dataclasses.dataclass +class PrepareRunnersRunPayload(code_action.RunActionPayload): + envs: list[EnvInfo] + # remove old env and create a new one from scratch even if the current one is valid. + # Useful for example if you changed something in venv manually and want to revert + # changes (just by running prepare it would be not solved because version of the + # packages are the same and they are already installed) + recreate: bool = False + + +class PrepareRunnersRunContext(code_action.RunActionContext): + def __init__( + self, + run_id: int, + ) -> None: + super().__init__(run_id=run_id) + + # project def pathes are stored also in context, because prepare envs can run + # tools like pip which expected 'normalized' project definition(=without + # additional features which finecode provides). So the usual workflow looks like + # normalizing(dumping) configuration first and then use dumped config for + # further handlers. + self.project_def_path_by_venv_dir_path: dict[pathlib.Path, pathlib.Path] = {} + # to avoid multiple writing and reading files in each action handler, save + # modified project definition here. It also can be used as extension point if + # for example additional dependencies should be installed by adding handler + # which inserts them into project definition instead of modying `install_deps` + # handler + self.project_def_by_venv_dir_path: dict[pathlib.Path, dict[str, typing.Any]] = ( + {} + ) + + async def init(self, initial_payload: PrepareRunnersRunPayload) -> None: + for env_info in initial_payload.envs: + self.project_def_path_by_venv_dir_path[env_info.venv_dir_path] = ( + env_info.project_def_path + ) + + +@dataclasses.dataclass +class PrepareRunnersRunResult(code_action.RunActionResult): + # `PrepareRunners` action is general, so make result general as well + errors: list[str] + + @override + def update(self, other: code_action.RunActionResult) -> None: + if not isinstance(other, PrepareRunnersRunResult): + return + self.errors += other.errors + + def to_text(self) -> str | textstyler.StyledText: + return "\n".join(self.errors) + + @property + def return_code(self) -> code_action.RunReturnCode: + if len(self.errors) == 0: + return code_action.RunReturnCode.SUCCESS + else: + return code_action.RunReturnCode.ERROR + + +class PrepareRunnersAction(code_action.Action): + PAYLOAD_TYPE = PrepareRunnersRunPayload + RUN_CONTEXT_TYPE = PrepareRunnersRunContext + RESULT_TYPE = PrepareRunnersRunResult diff --git a/finecode_extension_api/finecode_extension_api/code_action.py b/finecode_extension_api/src/finecode_extension_api/code_action.py similarity index 81% rename from finecode_extension_api/finecode_extension_api/code_action.py rename to finecode_extension_api/src/finecode_extension_api/code_action.py index 6d6efc4..e974628 100644 --- a/finecode_extension_api/finecode_extension_api/code_action.py +++ b/finecode_extension_api/src/finecode_extension_api/code_action.py @@ -2,19 +2,21 @@ import asyncio import collections.abc +import dataclasses import enum +import typing from pathlib import Path from typing import Generic, Protocol, TypeVar -from pydantic import BaseModel +from finecode_extension_api import partialresultscheduler, textstyler -from finecode_extension_api import partialresultscheduler +@dataclasses.dataclass +class ActionHandlerConfig: ... -class ActionHandlerConfig(BaseModel): ... - -class RunActionPayload(BaseModel): ... +@dataclasses.dataclass +class RunActionPayload: ... class RunReturnCode(enum.IntEnum): @@ -22,11 +24,12 @@ class RunReturnCode(enum.IntEnum): ERROR = 1 -class RunActionResult(BaseModel): +@dataclasses.dataclass +class RunActionResult: def update(self, other: RunActionResult) -> None: raise NotImplementedError() - def to_text(self) -> str: + def to_text(self) -> str | textstyler.StyledText: return str(self) @property @@ -77,7 +80,26 @@ def __init__(self, project_dir: Path, cache_dir: Path) -> None: self.cache_dir = cache_dir -class Action(Generic[RunPayloadType, RunContextType, RunResultType]): ... +@dataclasses.dataclass +class ActionConfig: + run_handlers_concurrently: bool = False + + +class Action(Generic[RunPayloadType, RunContextType, RunResultType]): + PAYLOAD_TYPE: typing.Type[RunActionPayload] = RunActionPayload + RUN_CONTEXT_TYPE: typing.Type[RunActionContext] = RunActionContext + RESULT_TYPE: typing.Type[RunActionResult] = RunActionResult + CONFIG_TYPE: typing.Type[ActionConfig] = ActionConfig + + +class StopActionRunWithResult(Exception): + def __init__(self, result: RunActionResult) -> None: + self.result = result + + +class ActionFailedException(Exception): + def __init__(self, message: str) -> None: + self.message = message InitializeCallable = collections.abc.Callable[[], None] diff --git a/finecode_extension_api/src/finecode_extension_api/common_types.py b/finecode_extension_api/src/finecode_extension_api/common_types.py new file mode 100644 index 0000000..5a21f86 --- /dev/null +++ b/finecode_extension_api/src/finecode_extension_api/common_types.py @@ -0,0 +1,26 @@ +import dataclasses + + +@dataclasses.dataclass +class Position: + line: int + character: int + + +@dataclasses.dataclass +class Range: + start: Position + end: Position + + +@dataclasses.dataclass +class TextDocumentIdentifier: + uri: str + + +@dataclasses.dataclass +class TextDocumentItem: + uri: str + language_id: str + version: int + text: str diff --git a/src/finecode/workspace_manager/cli_app/__init__.py b/finecode_extension_api/src/finecode_extension_api/interfaces/__init__.py similarity index 100% rename from src/finecode/workspace_manager/cli_app/__init__.py rename to finecode_extension_api/src/finecode_extension_api/interfaces/__init__.py diff --git a/finecode_extension_api/src/finecode_extension_api/interfaces/iactionrunner.py b/finecode_extension_api/src/finecode_extension_api/interfaces/iactionrunner.py new file mode 100644 index 0000000..aa78d09 --- /dev/null +++ b/finecode_extension_api/src/finecode_extension_api/interfaces/iactionrunner.py @@ -0,0 +1,22 @@ +from pathlib import Path +from typing import Any, Protocol + + +class IActionRunner(Protocol): + async def run_action( + self, name: str, payload: dict[str, Any] + ) -> dict[str, Any]: ... + + +class BaseRunActionException(Exception): + def __init__(self, message: str) -> None: + self.message = message + + +class ActionNotFound(BaseRunActionException): ... + + +class InvalidActionRunPayload(BaseRunActionException): ... + + +class ActionRunFailed(BaseRunActionException): ... diff --git a/finecode_extension_api/finecode_extension_api/interfaces/icache.py b/finecode_extension_api/src/finecode_extension_api/interfaces/icache.py similarity index 100% rename from finecode_extension_api/finecode_extension_api/interfaces/icache.py rename to finecode_extension_api/src/finecode_extension_api/interfaces/icache.py diff --git a/finecode_extension_api/finecode_extension_api/interfaces/icommandrunner.py b/finecode_extension_api/src/finecode_extension_api/interfaces/icommandrunner.py similarity index 100% rename from finecode_extension_api/finecode_extension_api/interfaces/icommandrunner.py rename to finecode_extension_api/src/finecode_extension_api/interfaces/icommandrunner.py diff --git a/finecode_extension_api/finecode_extension_api/interfaces/ifilemanager.py b/finecode_extension_api/src/finecode_extension_api/interfaces/ifilemanager.py similarity index 64% rename from finecode_extension_api/finecode_extension_api/interfaces/ifilemanager.py rename to finecode_extension_api/src/finecode_extension_api/interfaces/ifilemanager.py index 6334f13..9b21f6a 100644 --- a/finecode_extension_api/finecode_extension_api/interfaces/ifilemanager.py +++ b/finecode_extension_api/src/finecode_extension_api/interfaces/ifilemanager.py @@ -10,3 +10,9 @@ async def get_file_version(self, file_path: Path) -> str: ... async def save_file(self, file_path: Path, file_content) -> None: ... + + async def create_dir( + self, dir_path: Path, create_parents: bool = True, exist_ok: bool = True + ) -> None: ... + + async def remove_dir(self, dir_path: Path) -> None: ... diff --git a/finecode_extension_api/finecode_extension_api/interfaces/ilogger.py b/finecode_extension_api/src/finecode_extension_api/interfaces/ilogger.py similarity index 100% rename from finecode_extension_api/finecode_extension_api/interfaces/ilogger.py rename to finecode_extension_api/src/finecode_extension_api/interfaces/ilogger.py diff --git a/finecode_extension_api/finecode_extension_api/interfaces/iprocessexecutor.py b/finecode_extension_api/src/finecode_extension_api/interfaces/iprocessexecutor.py similarity index 100% rename from finecode_extension_api/finecode_extension_api/interfaces/iprocessexecutor.py rename to finecode_extension_api/src/finecode_extension_api/interfaces/iprocessexecutor.py diff --git a/finecode_extension_api/src/finecode_extension_api/interfaces/iprojectinfoprovider.py b/finecode_extension_api/src/finecode_extension_api/interfaces/iprojectinfoprovider.py new file mode 100644 index 0000000..6e3af54 --- /dev/null +++ b/finecode_extension_api/src/finecode_extension_api/interfaces/iprojectinfoprovider.py @@ -0,0 +1,12 @@ +import pathlib +from typing import Any, Protocol + + +class IProjectInfoProvider(Protocol): + def get_current_project_def_path(self) -> pathlib.Path: ... + + async def get_project_raw_config( + self, project_def_path: pathlib.Path + ) -> dict[str, Any]: ... + + async def get_current_project_raw_config(self) -> dict[str, Any]: ... diff --git a/finecode_extension_api/finecode_extension_api/partialresultscheduler.py b/finecode_extension_api/src/finecode_extension_api/partialresultscheduler.py similarity index 100% rename from finecode_extension_api/finecode_extension_api/partialresultscheduler.py rename to finecode_extension_api/src/finecode_extension_api/partialresultscheduler.py diff --git a/src/finecode/workspace_manager/config/__init__.py b/finecode_extension_api/src/finecode_extension_api/py.typed similarity index 100% rename from src/finecode/workspace_manager/config/__init__.py rename to finecode_extension_api/src/finecode_extension_api/py.typed diff --git a/finecode_extension_api/finecode_extension_api/textstyler.py b/finecode_extension_api/src/finecode_extension_api/textstyler.py similarity index 100% rename from finecode_extension_api/finecode_extension_api/textstyler.py rename to finecode_extension_api/src/finecode_extension_api/textstyler.py diff --git a/finecode_extension_runner/.gitignore b/finecode_extension_runner/.gitignore new file mode 100644 index 0000000..47b43fe --- /dev/null +++ b/finecode_extension_runner/.gitignore @@ -0,0 +1,13 @@ +__pycache__ +.coverage +.pytest_cache +.mypy_cache +.import_linter_cache +dist + +src/finecode_extension_runner/_version.py +src/*.egg-info + +.venvs +finecode_config_dump/ +build/ \ No newline at end of file diff --git a/finecode_extension_runner/README.md b/finecode_extension_runner/README.md new file mode 100644 index 0000000..b92e91e --- /dev/null +++ b/finecode_extension_runner/README.md @@ -0,0 +1 @@ +# FineCode Python Extension Runner diff --git a/finecode_extension_runner/pyproject.toml b/finecode_extension_runner/pyproject.toml new file mode 100644 index 0000000..2676c37 --- /dev/null +++ b/finecode_extension_runner/pyproject.toml @@ -0,0 +1,54 @@ +[project] +name = "finecode_extension_runner" +dynamic = ["version"] +description = "Extension runner component for FineCode" +authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] +readme = "README.md" +requires-python = ">=3.11, < 3.14" +dependencies = [ + "loguru==0.7.*", + "tomlkit==0.11.*", + "click==8.1.*", + "pydantic==2.10.*", + "platformdirs==4.3.*", + "pygls==2.0.0-a2", + "finecode_extension_api==0.3.*", + "deepmerge==2.0.*", +] + +[dependency-groups] +dev_workspace = ["build==1.2.2.post1", "finecode==0.3.0"] +dev = [{ include-group = "runtime" }, "pytest==7.4.*", "debugpy==1.8.*"] +dev_no_runtime = [ + "finecode_dev_common_preset==0.2.*", + # file_python_import_linter is temporary disabled, because it isn't ported to the new finecode_extension_api yet + # "fine_python_import_linter @ git+https://github.com/finecode-dev/finecode.git#subdirectory=extensions/fine_python_import_linter", +] + +[tool.finecode.env.dev_no_runtime.dependencies] +finecode_dev_common_preset = { path = "../finecode_dev_common_preset", editable = true } + +[build-system] +requires = ["setuptools>=64", "setuptools-scm>=8"] +build-backend = "setuptools.build_meta" + +[tool.finecode] +presets = [{ source = "finecode_dev_common_preset" }] + +[tool.importlinter] +root_package = "finecode_extension_runner" +include_external_packages = true + +[[tool.importlinter.contracts]] +id = "er-layered" +name = "ER layered architecture" +type = "layers" +layers = [ + "finecode_extension_runner.lsp_server", + "finecode_extension_runner.services", + "finecode_extension_runner.domain", +] + +[tool.setuptools_scm] +version_file = "src/finecode_extension_runner/_version.py" +root = ".." diff --git a/finecode_extension_runner/setup.py b/finecode_extension_runner/setup.py new file mode 100644 index 0000000..ff9f46d --- /dev/null +++ b/finecode_extension_runner/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="finecode_extension_runner", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/finecode_extension_runner/src/finecode_extension_runner/README.md b/finecode_extension_runner/src/finecode_extension_runner/README.md new file mode 100644 index 0000000..b92e91e --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/README.md @@ -0,0 +1 @@ +# FineCode Python Extension Runner diff --git a/src/finecode/workspace_manager/lsp_server/__init__.py b/finecode_extension_runner/src/finecode_extension_runner/__init__.py similarity index 100% rename from src/finecode/workspace_manager/lsp_server/__init__.py rename to finecode_extension_runner/src/finecode_extension_runner/__init__.py diff --git a/finecode_extension_runner/src/finecode_extension_runner/__main__.py b/finecode_extension_runner/src/finecode_extension_runner/__main__.py new file mode 100644 index 0000000..c55e863 --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/__main__.py @@ -0,0 +1,4 @@ +from finecode_extension_runner import cli + +if __name__ == "__main__": + cli.cli() diff --git a/src/finecode/workspace_manager/lsp_server/endpoints/__init__.py b/finecode_extension_runner/src/finecode_extension_runner/_services/__init__.py similarity index 100% rename from src/finecode/workspace_manager/lsp_server/endpoints/__init__.py rename to finecode_extension_runner/src/finecode_extension_runner/_services/__init__.py diff --git a/src/finecode/extension_runner/services.py b/finecode_extension_runner/src/finecode_extension_runner/_services/run_action.py similarity index 67% rename from src/finecode/extension_runner/services.py rename to finecode_extension_runner/src/finecode_extension_runner/_services/run_action.py index a611deb..84f9fbe 100644 --- a/src/finecode/extension_runner/services.py +++ b/finecode_extension_runner/src/finecode_extension_runner/_services/run_action.py @@ -1,29 +1,42 @@ import asyncio import collections.abc -import importlib +import dataclasses import inspect -import sys import time -import types import typing -from pathlib import Path +import deepmerge from loguru import logger +from pydantic.dataclasses import dataclass as pydantic_dataclass -from finecode.extension_runner import bootstrap, context, domain, global_state -from finecode.extension_runner import ( +from finecode_extension_api import code_action, textstyler +from finecode_extension_api.interfaces import iactionrunner +from finecode_extension_runner import context, domain, global_state +from finecode_extension_runner import ( partial_result_sender as partial_result_sender_module, ) -from finecode.extension_runner import project_dirs, run_utils, schemas -from finecode_extension_api import code_action, textstyler +from finecode_extension_runner import project_dirs, run_utils, schemas +from finecode_extension_runner.di import resolver as di_resolver +last_run_id: int = 0 +partial_result_sender: partial_result_sender_module.PartialResultSender +handler_config_merger = deepmerge.Merger( + [(list, ["override"]), (dict, ["merge"]), (set, ["override"])], + # all other types: + ["override"], + # strategies in the case where the types conflict: + ["override"], +) -class ActionFailedException(Exception): ... +class ActionFailedException(Exception): + def __init__(self, message: str) -> None: + self.message = message -document_requester: typing.Callable -document_saver: typing.Callable -partial_result_sender: partial_result_sender_module.PartialResultSender + +class StopWithResponse(Exception): + def __init__(self, response: schemas.RunActionResponse) -> None: + self.response = response def set_partial_result_sender(send_func: typing.Callable) -> None: @@ -33,214 +46,6 @@ def set_partial_result_sender(send_func: typing.Callable) -> None: ) -async def get_document(uri: str): - doc = await document_requester(uri) - return doc - - -async def save_document(uri: str, content: str): - await document_saver(uri, content) - - -async def update_config( - request: schemas.UpdateConfigRequest, -) -> schemas.UpdateConfigResponse: - project_path = Path(request.working_dir) - - actions: dict[str, domain.Action] = {} - for action_name, action_schema_obj in request.actions.items(): - handlers: list[domain.ActionHandler] = [] - for handler_obj in action_schema_obj.handlers: - handlers.append( - domain.ActionHandler( - name=handler_obj.name, - source=handler_obj.source, - config=handler_obj.config, - ) - ) - action = domain.Action( - name=action_name, - config=action_schema_obj.config, - handlers=handlers, - source=action_schema_obj.source, - ) - actions[action_name] = action - - global_state.runner_context = context.RunnerContext( - project=domain.Project( - name=request.project_name, - path=project_path, - actions=actions, - ), - ) - - # currently update_config is called only once directly after runner start. So we can - # bootstrap here. Should be changed after adding updating configuration on the fly. - bootstrap.bootstrap( - get_document_func=get_document, save_document_func=save_document - ) - - return schemas.UpdateConfigResponse() - - -def resolve_func_args_with_di( - func: typing.Callable, - known_args: dict[str, typing.Callable[[typing.Any], typing.Any]] | None = None, - params_to_ignore: list[str] | None = None, -): - func_parameters = inspect.signature(func).parameters - func_annotations = inspect.get_annotations(func, eval_str=True) - args: dict[str, typing.Any] = {} - for param_name in func_parameters.keys(): - # default object constructor(__init__) has signature - # __init__(self, *args, **kwargs) - # args and kwargs have no annotation and should not be filled by DI resolver. - # Ignore them. - if ( - params_to_ignore is not None and param_name in params_to_ignore - ) or param_name in ["args", "kwargs"]: - continue - elif known_args is not None and param_name in known_args: - param_type = func_annotations[param_name] - # value in known args is a callable factory to instantiate param value - args[param_name] = known_args[param_name](param_type) - else: - # TODO: handle errors - param_type = func_annotations[param_name] - param_value = bootstrap.get_service_instance(param_type) - args[param_name] = param_value - - return args - - -def create_action_exec_info(action: domain.Action) -> domain.ActionExecInfo: - try: - action_type_def = run_utils.import_module_member_by_source_str(action.source) - except Exception as e: - logger.error(f"Error importing action type: {e}") - raise e - - # typing.TypeAliasType is available in Python 3.12+ - if hasattr(typing, "TypeAliasType") and not isinstance( - action_type_def, typing.TypeAliasType - ): - raise Exception("Action definition expected to be a type") - - action_type_alias = action_type_def.__value__ - - if not isinstance(action_type_alias, typing._GenericAlias): - raise Exception( - "Action definition expected to be an instantiation of" - " finecode_extension_api.code_action.Action type" - ) - - try: - unpack_with_action = next(iter(action_type_alias)) - except StopIteration: - raise Exception("Action type definition is invalid: no action type alias?") - - # typing.Unpack cannot used in isinstance: - # TypeError: typing.Unpack cannot be used with isinstance() - # if not isinstance(unpack_with_action,typing.Unpack): - # raise Exception("Action type definition is invalid: type alias is not unpack") - - if len(unpack_with_action.__args__) != 1: - raise Exception("Action type definition is invalid: expected 1 Action instance") - - action_generic_alias = unpack_with_action.__args__[0] - action_args = action_generic_alias.__args__ - - if len(action_args) != 3: - raise Exception( - "Action type definition is invalid: Action type expects 3 arguments" - ) - - payload_type, run_context_type, _ = action_args - - # TODO: validate that classes and correct subclasses? - - action_exec_info = domain.ActionExecInfo( - payload_type=payload_type, run_context_type=run_context_type - ) - return action_exec_info - - -async def run_subresult_coros_concurrently( - coros: list[collections.abc.Coroutine], - send_partial_results: bool, - partial_result_token: int | str, - partial_result_sender: partial_result_sender_module.PartialResultSender, - action_name: str, - run_id: int, -) -> code_action.RunActionResult | None: - coros_tasks: list[asyncio.Task] = [] - try: - async with asyncio.TaskGroup() as tg: - for coro in coros: - coro_task = tg.create_task(coro) - coros_tasks.append(coro_task) - except ExceptionGroup as eg: - logger.error(f"R{run_id} | {eg}") - for exc in eg.exceptions: - logger.exception(exc) - raise ActionFailedException( - f"Concurrent running action handlers of '{action_name}' failed(Run {run_id}). See logs for more details" - ) - - action_subresult: code_action.RunActionResult | None = None - for coro_task in coros_tasks: - coro_result = coro_task.result() - if coro_result is not None: - if action_subresult is None: - action_subresult = coro_result - else: - action_subresult.update(coro_result) - - if send_partial_results: - await partial_result_sender.schedule_sending( - partial_result_token, action_subresult - ) - return None - else: - return action_subresult - - -async def run_subresult_coros_sequentially( - coros: list[collections.abc.Coroutine], - send_partial_results: bool, - partial_result_token: int | str, - partial_result_sender: partial_result_sender_module.PartialResultSender, - action_name: str, - run_id: int, -) -> code_action.RunActionResult | None: - action_subresult: code_action.RunActionResult | None = None - for coro in coros: - try: - coro_result = await coro - except Exception as e: - logger.exception(e) - raise ActionFailedException( - f"Running action handlers of '{action_name}' failed(Run {run_id}): {e}" - ) - - if coro_result is not None: - if action_subresult is None: - action_subresult = coro_result - else: - action_subresult.update(coro_result) - - if send_partial_results: - await partial_result_sender.schedule_sending( - partial_result_token, action_subresult - ) - return None - else: - return action_subresult - - -last_run_id: int = 0 - - async def run_action( request: schemas.RunActionRequest, options: schemas.RunActionOptions ) -> schemas.RunActionResponse: @@ -288,7 +93,8 @@ async def run_action( # TODO: catch validation errors payload: code_action.RunActionPayload | None = None if action_exec_info.payload_type is not None: - payload = action_exec_info.payload_type(**request.params) + payload_type_with_validation = pydantic_dataclass(action_exec_info.payload_type) + payload = payload_type_with_validation(**request.params) run_context: code_action.RunActionContext | None = None if action_exec_info.run_context_type is not None: @@ -297,6 +103,7 @@ async def run_action( known_args={"run_id": lambda _: run_id}, params_to_ignore=["self"], ) + run_context = action_exec_info.run_context_type(**constructor_args) # TODO: handler errors await run_context.init(initial_payload=payload) @@ -376,11 +183,15 @@ async def run_action( subresult_task = tg.create_task(coro) subresults_tasks.append(subresult_task) except ExceptionGroup as eg: - logger.error(eg) + errors: list[str] = [] for exc in eg.exceptions: - logger.exception(exc) + if not isinstance(exc, ActionFailedException): + logger.error("Unexpected exception:") + logger.exception(exc) + else: + errors.append(exc.message) raise ActionFailedException( - f"Running action handlers of '{action.name}' failed(Run {run_id})." + f"Running action handlers of '{action.name}' failed(Run {run_id}): {errors}." " See ER logs for more details" ) @@ -416,8 +227,8 @@ async def run_action( ) handlers_tasks.append(handler_task) except ExceptionGroup as eg: - logger.error(eg) for exc in eg.exceptions: + # TODO: expected / unexpected? logger.exception(exc) raise ActionFailedException( f"Running action handlers of '{action.name}' failed" @@ -433,15 +244,18 @@ async def run_action( action_result.update(coro_result) else: for handler in action.handlers: - handler_result = await execute_action_handler( - handler=handler, - payload=payload, - run_context=run_context, - run_id=run_id, - action_context=action_context, - action_exec_info=action_exec_info, - runner_context=runner_context, - ) + try: + handler_result = await execute_action_handler( + handler=handler, + payload=payload, + run_context=run_context, + run_id=run_id, + action_context=action_context, + action_exec_info=action_exec_info, + runner_context=runner_context, + ) + except ActionFailedException as exception: + raise exception if handler_result is not None: if action_result is None: @@ -449,15 +263,39 @@ async def run_action( else: action_result.update(handler_result) + end_time = time.time_ns() + duration = (end_time - start_time) / 1_000_000 + logger.trace( + f"R{run_id} | Run action end '{request.action_name}', duration: {duration}ms" + ) + + if not isinstance(action_result, code_action.RunActionResult): + logger.error( + f"R{run_id} | Unexpected result type: {type(action_result).__name__}" + ) + raise ActionFailedException( + f"Unexpected result type: {type(action_result).__name__}" + ) + + response = action_result_to_run_action_response( + action_result, options.result_format + ) + return response + + +def action_result_to_run_action_response( + action_result: code_action.RunActionResult, + asked_result_format: typing.Literal["json"] | typing.Literal["string"], +) -> schemas.RunActionResponse: serialized_result: dict[str, typing.Any] | str | None = None result_format = "string" run_return_code = code_action.RunReturnCode.SUCCESS if isinstance(action_result, code_action.RunActionResult): run_return_code = action_result.return_code - if options.result_format == "json": - serialized_result = action_result.model_dump(mode="json") + if asked_result_format == "json": + serialized_result = dataclasses.asdict(action_result) result_format = "json" - elif options.result_format == "string": + elif asked_result_format == "string": result_text = action_result.to_text() if isinstance(result_text, textstyler.StyledText): serialized_result = result_text.to_json() @@ -467,21 +305,8 @@ async def run_action( result_format = "string" else: raise ActionFailedException( - f"Unsupported result format: {options.result_format}" + f"Unsupported result format: {asked_result_format}" ) - elif action_result is not None: - logger.error( - f"R{run_id} | Unexpected result type: {type(action_result).__name__}" - ) - raise ActionFailedException( - f"Unexpected result type: {type(action_result).__name__}" - ) - - end_time = time.time_ns() - duration = (end_time - start_time) / 1_000_000 - logger.trace( - f"R{run_id} | Run action end '{request.action_name}', duration: {duration}ms" - ) return schemas.RunActionResponse( result=serialized_result, format=result_format, @@ -489,6 +314,59 @@ async def run_action( ) +def create_action_exec_info(action: domain.Action) -> domain.ActionExecInfo: + try: + action_type_def = run_utils.import_module_member_by_source_str(action.source) + except Exception as e: + logger.error(f"Error importing action type: {e}") + raise e + + if not issubclass(action_type_def, code_action.Action): + raise Exception( + "Action class expected to be a subclass of finecode_extension_api.code_action.Action" + ) + + payload_type = action_type_def.PAYLOAD_TYPE + run_context_type = action_type_def.RUN_CONTEXT_TYPE + + # TODO: validate that classes and correct subclasses? + + action_exec_info = domain.ActionExecInfo( + payload_type=payload_type, run_context_type=run_context_type + ) + return action_exec_info + + +def resolve_func_args_with_di( + func: typing.Callable, + known_args: dict[str, typing.Callable[[typing.Any], typing.Any]] | None = None, + params_to_ignore: list[str] | None = None, +): + func_parameters = inspect.signature(func).parameters + func_annotations = inspect.get_annotations(func, eval_str=True) + args: dict[str, typing.Any] = {} + for param_name in func_parameters.keys(): + # default object constructor(__init__) has signature + # __init__(self, *args, **kwargs) + # args and kwargs have no annotation and should not be filled by DI resolver. + # Ignore them. + if ( + params_to_ignore is not None and param_name in params_to_ignore + ) or param_name in ["args", "kwargs"]: + continue + elif known_args is not None and param_name in known_args: + param_type = func_annotations[param_name] + # value in known args is a callable factory to instantiate param value + args[param_name] = known_args[param_name](param_type) + else: + # TODO: handle errors + param_type = func_annotations[param_name] + param_value = di_resolver.get_service_instance(param_type) + args[param_name] = param_value + + return args + + async def execute_action_handler( handler: domain.ActionHandler, payload: code_action.RunActionPayload | None, @@ -497,7 +375,7 @@ async def execute_action_handler( action_exec_info: domain.ActionExecInfo, action_context: code_action.ActionContext, runner_context: context.RunnerContext, -) -> code_action.RunActionResult | None: +) -> code_action.RunActionResult: logger.trace(f"R{run_id} | Run {handler.name} on {str(payload)[:100]}...") start_time = time.time_ns() execution_result: code_action.RunActionResult | None = None @@ -523,9 +401,22 @@ async def execute_action_handler( " could not be imported" ) logger.error(error) - return None + raise ActionFailedException( + f"Import of action handler '{handler.name}' failed(Run {run_id}): {handler.source}" + ) - handler_raw_config = handler.config + handler_global_config = runner_context.project.action_handler_configs.get( + handler.source, None + ) + handler_raw_config = {} + if handler_global_config is not None: + handler_raw_config = handler_global_config + if handler_raw_config == {}: + # still empty, just assign + handler_raw_config = handler.config + else: + # not empty anymore, deep merge + handler_config_merger.merge(handler_raw_config, handler.config) def get_handler_config(param_type): # TODO: validation errors @@ -576,9 +467,12 @@ def get_process_executor(param_type): await initialize_callable_result except Exception as e: logger.error( - f"R{run_id} | Failed to initialize action {handler.name}: {e}" + f"R{run_id} | Failed to initialize action handler {handler.name}: {e}" ) - return None + raise ActionFailedException( + f"Initialisation of action handler '{handler.name}' failed(Run {run_id}): {e}" + ) + exec_info.status = domain.ActionHandlerExecInfoStatus.INITIALIZED def get_run_payload(param_type): @@ -603,10 +497,21 @@ def get_run_context(param_type): execution_result = await call_result else: execution_result = call_result - except Exception as e: - logger.exception(e) + except Exception as exception: + if isinstance(exception, code_action.StopActionRunWithResult): + action_result = exception.result + response = action_result_to_run_action_response(action_result, "string") + raise StopWithResponse(response=response) + elif isinstance(exception, iactionrunner.BaseRunActionException) or isinstance( + exception, code_action.ActionFailedException + ): + error_str = exception.message + else: + logger.error("Unhandled exception in action handler:") + logger.exception(exception) + error_str = str(exception) raise ActionFailedException( - f"Running action handler '{handler.name}' failed(Run {run_id}): {e}" + f"Running action handler '{handler.name}' failed(Run {run_id}): {error_str}" ) end_time = time.time_ns() @@ -618,151 +523,77 @@ def get_run_context(param_type): return execution_result -def reload_action(action_name: str) -> None: - if global_state.runner_context is None: - # TODO: raise error - return - - project_def = global_state.runner_context.project - +async def run_subresult_coros_concurrently( + coros: list[collections.abc.Coroutine], + send_partial_results: bool, + partial_result_token: int | str, + partial_result_sender: partial_result_sender_module.PartialResultSender, + action_name: str, + run_id: int, +) -> code_action.RunActionResult | None: + coros_tasks: list[asyncio.Task] = [] try: - action_obj = project_def.actions[action_name] - except KeyError: - available_actions_str = ",".join( - [action_name for action_name in project_def.actions] - ) - logger.warning( - f"Action {action_name} not found." - f" Available actions: {available_actions_str}" - ) - # TODO: raise error - return - - actions_to_remove: list[str] = [ - action_name, - *[handler.name for handler in action_obj.handlers], - ] - - for _action_name in actions_to_remove: - try: - del global_state.runner_context.action_handlers_instances_by_name[ - _action_name - ] - logger.trace(f"Removed '{_action_name}' instance from cache") - except KeyError: - logger.info( - f"Tried to reload action '{_action_name}', but it was not found" - ) - - if ( - _action_name - in global_state.runner_context.action_handlers_exec_info_by_name - ): - shutdown_action_handler( - action_handler_name=_action_name, - exec_info=global_state.runner_context.action_handlers_exec_info_by_name[ - _action_name - ], - ) - - try: - action_obj = project_def.actions[action_name] - except KeyError: - logger.warning(f"Definition of action {action_name} not found") - continue - - action_source = action_obj.source - if action_source is None: - continue - action_package = action_source.split(".")[0] - - loaded_package_modules = dict( - [ - (key, value) - for key, value in sys.modules.items() - if key.startswith(action_package) - and isinstance(value, types.ModuleType) - ] + async with asyncio.TaskGroup() as tg: + for coro in coros: + coro_task = tg.create_task(coro) + coros_tasks.append(coro_task) + except ExceptionGroup as eg: + logger.error(f"R{run_id} | {eg}") + for exc in eg.exceptions: + logger.exception(exc) + raise ActionFailedException( + f"Concurrent running action handlers of '{action_name}' failed(Run {run_id}). See logs for more details" ) - # delete references to these loaded modules from sys.modules - for key in loaded_package_modules: - del sys.modules[key] - - logger.trace(f"Remove modules of package '{action_package}' from cache") - - -def resolve_package_path(package_name: str) -> str: - try: - package_path = importlib.util.find_spec( - package_name - ).submodule_search_locations[0] - except Exception: - raise ValueError(f"Cannot find package {package_name}") - - return package_path - - -def document_did_open(document_uri: str) -> None: - global_state.runner_context.docs_owned_by_client.append(document_uri) - - -def document_did_close(document_uri: str) -> None: - global_state.runner_context.docs_owned_by_client.remove(document_uri) - - -def shutdown_action_handler( - action_handler_name: str, exec_info: domain.ActionHandlerExecInfo -) -> None: - # action handler exec info expected to exist in runner_context - if exec_info.status == domain.ActionHandlerExecInfoStatus.SHUTDOWN: - return + action_subresult: code_action.RunActionResult | None = None + for coro_task in coros_tasks: + coro_result = coro_task.result() + if coro_result is not None: + if action_subresult is None: + action_subresult = coro_result + else: + action_subresult.update(coro_result) - if ( - exec_info.lifecycle is not None - and exec_info.lifecycle.on_shutdown_callable is not None - ): - logger.trace(f"Shutdown {action_handler_name} action handler") - try: - exec_info.lifecycle.on_shutdown_callable() - except Exception as e: - logger.error(f"Failed to shutdown action {action_handler_name}: {e}") - exec_info.status = domain.ActionHandlerExecInfoStatus.SHUTDOWN - - -def shutdown_all_action_handlers() -> None: - logger.trace("Shutdown all action handlers") - for ( - action_handler_name, - exec_info, - ) in global_state.runner_context.action_handlers_exec_info_by_name.items(): - shutdown_action_handler( - action_handler_name=action_handler_name, exec_info=exec_info + if send_partial_results: + await partial_result_sender.schedule_sending( + partial_result_token, action_subresult ) + return None + else: + return action_subresult -def exit_action_handler( - action_handler_name: str, exec_info: domain.ActionHandlerExecInfo -) -> None: - # action handler exec info expected to exist in runner_context - if ( - exec_info.lifecycle is not None - and exec_info.lifecycle.on_exit_callable is not None - ): - logger.trace(f"Exit {action_handler_name} action handler") +async def run_subresult_coros_sequentially( + coros: list[collections.abc.Coroutine], + send_partial_results: bool, + partial_result_token: int | str, + partial_result_sender: partial_result_sender_module.PartialResultSender, + action_name: str, + run_id: int, +) -> code_action.RunActionResult | None: + action_subresult: code_action.RunActionResult | None = None + for coro in coros: try: - exec_info.lifecycle.on_exit_callable() + coro_result = await coro except Exception as e: - logger.error(f"Failed to exit action {action_handler_name}: {e}") + logger.error( + f"Unhandled exception in subresult coroutine({action_name}, run {run_id}):" + ) + logger.exception(e) + raise ActionFailedException( + f"Running action handlers of '{action_name}' failed(Run {run_id}): {e}" + ) + if coro_result is not None: + if action_subresult is None: + action_subresult = coro_result + else: + action_subresult.update(coro_result) -def exit_all_action_handlers() -> None: - logger.trace("Exit all action handlers") - for ( - action_handler_name, - exec_info, - ) in global_state.runner_context.action_handlers_exec_info_by_name.items(): - exit_action_handler( - action_handler_name=action_handler_name, exec_info=exec_info + if send_partial_results: + await partial_result_sender.schedule_sending( + partial_result_token, action_subresult ) - global_state.runner_context.action_handlers_exec_info_by_name = {} + return None + else: + return action_subresult diff --git a/finecode_extension_runner/src/finecode_extension_runner/action_handlers/__init__.py b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/__init__.py new file mode 100644 index 0000000..7f3bdaf --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/__init__.py @@ -0,0 +1,17 @@ +from .dump_config import DumpConfigHandler +from .dump_config_save import DumpConfigSaveHandler +from .prepare_envs_install_deps import PrepareEnvsInstallDepsHandler +from .prepare_envs_read_configs import PrepareEnvsReadConfigsHandler +from .prepare_runners_install_runner_and_presets import ( + PrepareRunnersInstallRunnerAndPresetsHandler, +) +from .prepare_runners_read_configs import PrepareRunnersReadConfigsHandler + +__all__ = [ + "DumpConfigHandler", + "PrepareEnvsInstallDepsHandler", + "PrepareEnvsReadConfigsHandler", + "PrepareRunnersInstallRunnerAndPresetsHandler", + "PrepareRunnersReadConfigsHandler", + "DumpConfigSaveHandler", +] diff --git a/finecode_extension_runner/src/finecode_extension_runner/action_handlers/dependency_config_utils.py b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/dependency_config_utils.py new file mode 100644 index 0000000..1a0e93e --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/dependency_config_utils.py @@ -0,0 +1,98 @@ +import pathlib +import typing + + +def make_project_config_pip_compatible( + project_raw_config: dict[str, typing.Any], config_file_path: pathlib.Path +) -> None: + finecode_config = project_raw_config.get("tool", {}).get("finecode", {}) + # apply changes to dependencies from env configuration to deps groups + for env_name in finecode_config.get("env", {}).keys(): + make_env_deps_pip_compatible( + env_name=env_name, + project_raw_config=project_raw_config, + config_file_path=config_file_path, + ) + + +def make_env_deps_pip_compatible( + env_name: str, + project_raw_config: dict[str, typing.Any], + config_file_path: pathlib.Path, +) -> None: + env_config = ( + project_raw_config.get("tool", {}) + .get("finecode", {}) + .get("env", {}) + .get(env_name, None) + ) + if env_config is None or "dependencies" not in env_config: + return + + env_deps_group = project_raw_config.get("dependency-groups", {}).get(env_name, []) + dependencies = env_config["dependencies"] + for dep_name, dep_params in dependencies.items(): + # handle 'path'. 'editable' cannot be handled here because dependency + # specifier doesn't support it. It will read and processed by + # `install_deps` action + if "path" in dep_params: + # replace dependency version / source in dependency group to this path + # + # check all dependencies because it can be duplicated: e.g. as explicit + # dependency and as dependency of action handler. + dep_indexes_in_group: list[int] = [] + for idx, dep in enumerate(env_deps_group): + if isinstance(dep, dict): + if "include-group" in dep: + included_group = dep["include-group"] + make_env_deps_pip_compatible( + env_name=included_group, + project_raw_config=project_raw_config, + config_file_path=config_file_path, + ) + elif isinstance(dep, str): + if get_dependency_name(dep) == dep_name: + dep_indexes_in_group.append(idx) + + if len(dep_indexes_in_group) == 0: + continue + + resolved_path_to_dep = pathlib.Path(dep_params["path"]) + if not resolved_path_to_dep.is_absolute(): + # resolve relative to project dir where project def file is + resolved_path_to_dep = config_file_path.parent / resolved_path_to_dep + new_dep_str_in_group = ( + f"{dep_name} @ file://{resolved_path_to_dep.as_posix()}" + ) + for idx in dep_indexes_in_group: + env_deps_group[idx] = new_dep_str_in_group + + +def get_dependency_name(dependency_str: str) -> str: + # simplified way for now: find the first character which is not allowed in package + # name + for idx, ch in enumerate(dependency_str): + if not ch.isalnum() and ch not in "-_": + return dependency_str[:idx] + + # dependency can consist also just of package name without version + return dependency_str + + +def raw_dep_to_dep_dict(raw_dep: str, env_deps_config: dict) -> dict[str, str | bool]: + name = get_dependency_name(raw_dep) + version_or_source = raw_dep[len(name) :] + editable = env_deps_config.get(name, {}).get("editable", False) + dep_dict = { + "name": name, + "version_or_source": version_or_source, + "editable": editable, + } + return dep_dict + + +__all__ = [ + "make_project_config_pip_compatible", + "get_dependency_name", + "raw_dep_to_dep_dict", +] diff --git a/finecode_extension_runner/src/finecode_extension_runner/action_handlers/dump_config.py b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/dump_config.py new file mode 100644 index 0000000..263ee38 --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/dump_config.py @@ -0,0 +1,33 @@ +import dataclasses +import pathlib + +from finecode_extension_api import code_action +from finecode_extension_api.actions import dump_config as dump_config_action +from finecode_extension_api.interfaces import ifilemanager + + +@dataclasses.dataclass +class DumpConfigHandlerConfig(code_action.ActionHandlerConfig): ... + + +class DumpConfigHandler( + code_action.ActionHandler[ + dump_config_action.DumpConfigAction, DumpConfigHandlerConfig + ] +): + async def run( + self, + payload: dump_config_action.DumpConfigRunPayload, + run_context: dump_config_action.DumpConfigRunContext, + ) -> dump_config_action.DumpConfigRunResult: + # presets are resolved, remove tool.finecode.presets key to avoid repeating + # resolving if dump config is processed + finecode_config = run_context.raw_config_dump.get("tool", {}).get( + "finecode", {} + ) + if "presets" in finecode_config: + del finecode_config["presets"] + + return dump_config_action.DumpConfigRunResult( + config_dump=run_context.raw_config_dump + ) diff --git a/finecode_extension_runner/src/finecode_extension_runner/action_handlers/dump_config_save.py b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/dump_config_save.py new file mode 100644 index 0000000..2252f39 --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/dump_config_save.py @@ -0,0 +1,40 @@ +import dataclasses + +import tomlkit + +from finecode_extension_api import code_action +from finecode_extension_api.actions import dump_config as dump_config_action +from finecode_extension_api.interfaces import ifilemanager + + +@dataclasses.dataclass +class DumpConfigSaveHandlerConfig(code_action.ActionHandlerConfig): ... + + +class DumpConfigSaveHandler( + code_action.ActionHandler[ + dump_config_action.DumpConfigAction, DumpConfigSaveHandlerConfig + ] +): + def __init__( + self, + file_manager: ifilemanager.IFileManager, + ) -> None: + self.file_manager = file_manager + + async def run( + self, + payload: dump_config_action.DumpConfigRunPayload, + run_context: dump_config_action.DumpConfigRunContext, + ) -> dump_config_action.DumpConfigRunResult: + raw_config_str = tomlkit.dumps(run_context.raw_config_dump) + target_file_dir_path = payload.target_file_path.parent + + await self.file_manager.create_dir(dir_path=target_file_dir_path) + await self.file_manager.save_file( + file_path=payload.target_file_path, file_content=raw_config_str + ) + + return dump_config_action.DumpConfigRunResult( + config_dump=run_context.raw_config_dump + ) diff --git a/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_envs_install_deps.py b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_envs_install_deps.py new file mode 100644 index 0000000..8f87893 --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_envs_install_deps.py @@ -0,0 +1,107 @@ +import asyncio +import dataclasses +import itertools +import shutil + +from finecode_extension_api import code_action +from finecode_extension_api.actions import prepare_envs as prepare_envs_action +from finecode_extension_api.interfaces import ( + iactionrunner, + ilogger, + iprojectinfoprovider, +) +from finecode_extension_runner.action_handlers import dependency_config_utils + + +@dataclasses.dataclass +class PrepareEnvsInstallDepsHandlerConfig(code_action.ActionHandlerConfig): ... + + +class PrepareEnvsInstallDepsHandler( + code_action.ActionHandler[ + prepare_envs_action.PrepareEnvsAction, PrepareEnvsInstallDepsHandlerConfig + ] +): + def __init__( + self, action_runner: iactionrunner.IActionRunner, logger: ilogger.ILogger + ) -> None: + self.action_runner = action_runner + self.logger = logger + + async def run( + self, + payload: prepare_envs_action.PrepareEnvsRunPayload, + run_context: prepare_envs_action.PrepareEnvsRunContext, + ) -> prepare_envs_action.PrepareEnvsRunResult: + envs = payload.envs + + install_deps_tasks: list[asyncio.Task] = [] + try: + async with asyncio.TaskGroup() as tg: + for env in envs: + project_def = run_context.project_def_by_venv_dir_path[ + env.venv_dir_path + ] + + # straightforward solution for now + deps_groups = project_def.get("dependency-groups", {}) + env_raw_deps = deps_groups.get(env.name, []) + env_deps_config = ( + project_def.get("tool", {}) + .get("finecode", {}) + .get("env", {}) + .get(env.name, {}) + .get("dependencies", {}) + ) + dependencies = [] + + process_raw_deps( + env_raw_deps, env_deps_config, dependencies, deps_groups + ) + + task = tg.create_task( + self.action_runner.run_action( + name="install_deps_in_env", + payload={ + "env_name": env.name, + "venv_dir_path": env.venv_dir_path, + "project_dir_path": env.project_def_path.parent, + "dependencies": dependencies, + }, + ) + ) + install_deps_tasks.append(task) + except ExceptionGroup as eg: + error_str = ". ".join([str(exception) for exception in eg.exceptions]) + raise code_action.ActionFailedException(error_str) + + install_deps_results = [task.result() for task in install_deps_tasks] + errors: list[str] = list( + itertools.chain.from_iterable( + [result["errors"] for result in install_deps_results] + ) + ) + + return prepare_envs_action.PrepareEnvsRunResult(errors=errors) + + +def process_raw_deps( + raw_deps: list, env_deps_config, dependencies, deps_groups +) -> None: + for raw_dep in raw_deps: + if isinstance(raw_dep, str): + name = dependency_config_utils.get_dependency_name(raw_dep) + version_or_source = raw_dep[len(name) :] + editable = env_deps_config.get(name, {}).get("editable", False) + dependencies.append( + { + "name": name, + "version_or_source": version_or_source, + "editable": editable, + } + ) + elif isinstance(raw_dep, dict) and "include-group" in raw_dep: + included_group_deps = deps_groups.get(raw_dep["include-group"], []) + process_raw_deps( + included_group_deps, env_deps_config, dependencies, deps_groups + ) diff --git a/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_envs_read_configs.py b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_envs_read_configs.py new file mode 100644 index 0000000..49c4cbf --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_envs_read_configs.py @@ -0,0 +1,72 @@ +import asyncio +import dataclasses +import pathlib +import shutil +import typing + +from finecode_extension_api import code_action +from finecode_extension_api.actions import prepare_envs as prepare_envs_action +from finecode_extension_api.interfaces import ( + iactionrunner, + ilogger, + iprojectinfoprovider, +) +from finecode_extension_runner.action_handlers import dependency_config_utils + + +@dataclasses.dataclass +class PrepareEnvsReadConfigsHandlerConfig(code_action.ActionHandlerConfig): ... + + +class PrepareEnvsReadConfigsHandler( + code_action.ActionHandler[ + prepare_envs_action.PrepareEnvsAction, PrepareEnvsReadConfigsHandlerConfig + ] +): + def __init__( + self, + action_runner: iactionrunner.IActionRunner, + project_info_provider: iprojectinfoprovider.IProjectInfoProvider, + logger: ilogger.ILogger, + ) -> None: + self.action_runner = action_runner + self.project_info_provider = project_info_provider + self.logger = logger + + async def run( + self, + payload: prepare_envs_action.PrepareEnvsRunPayload, + run_context: prepare_envs_action.PrepareEnvsRunContext, + ) -> prepare_envs_action.PrepareEnvsRunResult: + project_defs_pathes = set( + [env_info.project_def_path for env_info in payload.envs] + ) + raw_config_by_project_def_path: dict[pathlib.Path, dict[str, typing.Any]] = {} + + get_config_tasks: list[asyncio.Task] = [] + async with asyncio.TaskGroup() as tg: + for project_def_path in project_defs_pathes: + task = tg.create_task( + self.project_info_provider.get_project_raw_config(project_def_path) + ) + get_config_tasks.append(task) + + for idx, project_def_path in enumerate(project_defs_pathes): + project_raw_config = get_config_tasks[idx].result() + dependency_config_utils.make_project_config_pip_compatible( + project_raw_config, project_def_path + ) + raw_config_by_project_def_path[project_def_path] = project_raw_config + + for env_info in payload.envs: + run_context.project_def_path_by_venv_dir_path[env_info.venv_dir_path] = ( + env_info.project_def_path + ) + project_raw_config = raw_config_by_project_def_path[ + env_info.project_def_path + ] + run_context.project_def_by_venv_dir_path[env_info.venv_dir_path] = ( + project_raw_config + ) + + return prepare_envs_action.PrepareEnvsRunResult(errors=[]) diff --git a/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_runners_install_runner_and_presets.py b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_runners_install_runner_and_presets.py new file mode 100644 index 0000000..f16dbfe --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_runners_install_runner_and_presets.py @@ -0,0 +1,176 @@ +import asyncio +import dataclasses +import itertools +import shutil +import typing + +from finecode_extension_api import code_action +from finecode_extension_api.actions import prepare_runners as prepare_runners_action +from finecode_extension_api.interfaces import ( + iactionrunner, + ilogger, + iprojectinfoprovider, +) +from finecode_extension_runner.action_handlers import dependency_config_utils + + +@dataclasses.dataclass +class PrepareRunnersInstallRunnerAndPresetsHandlerConfig( + code_action.ActionHandlerConfig +): ... + + +class PrepareRunnersInstallRunnerAndPresetsHandler( + code_action.ActionHandler[ + prepare_runners_action.PrepareRunnersAction, + PrepareRunnersInstallRunnerAndPresetsHandlerConfig, + ] +): + def __init__( + self, action_runner: iactionrunner.IActionRunner, logger: ilogger.ILogger + ) -> None: + self.action_runner = action_runner + self.logger = logger + + async def run( + self, + payload: prepare_runners_action.PrepareRunnersRunPayload, + run_context: prepare_runners_action.PrepareRunnersRunContext, + ) -> prepare_runners_action.PrepareRunnersRunResult: + # find finecode_extension_runner in deps + # find presets in config and their version in deps + # install all these packages + envs = payload.envs + + dependencies_by_env: dict[str, list[dict]] = {} + for env in envs: + project_def = run_context.project_def_by_venv_dir_path[env.venv_dir_path] + project_def_path = run_context.project_def_path_by_venv_dir_path[ + env.venv_dir_path + ] + try: + dependencies = get_dependencies_in_project_raw_config( + project_def, env.name + ) + except FailedToGetDependencies as exception: + raise code_action.ActionFailedException( + f"Failed to get dependencies of env {env.name} in {project_def_path} (install_runner_and_presets handler)" + ) + dependencies_by_env[env.name] = dependencies + + install_deps_tasks: list[asyncio.Task] = [] + try: + async with asyncio.TaskGroup() as tg: + for env in envs: + task = tg.create_task( + self.action_runner.run_action( + name="install_deps_in_env", + payload={ + "env_name": env.name, + "venv_dir_path": env.venv_dir_path, + "project_dir_path": env.project_def_path.parent, + "dependencies": dependencies_by_env[env.name], + }, + ) + ) + install_deps_tasks.append(task) + except ExceptionGroup as eg: + errors: list[str] = [] + for exception in eg.exceptions: + if isinstance(exception, iactionrunner.BaseRunActionException): + errors.append(exception.message) + else: + # unexpected exception + error_str = ". ".join( + [str(exception) for exception in eg.exceptions] + ) + raise code_action.ActionFailedException(error_str) + + result = prepare_runners_action.PrepareRunnersRunResult(errors=errors) + raise code_action.StopActionRunWithResult(result=result) + + install_deps_results = [task.result() for task in install_deps_tasks] + errors: list[str] = list( + itertools.chain.from_iterable( + [result["errors"] for result in install_deps_results] + ) + ) + result = prepare_runners_action.PrepareRunnersRunResult(errors=errors) + + return result + + +class FailedToGetDependencies(Exception): + def __init__(self, message: str) -> None: + self.message = message + + +def get_dependencies_in_project_raw_config( + project_raw_config: dict[str, typing.Any], env_name: str +): + # returns dependencies: presets and extension runner + presets_in_config = ( + project_raw_config.get("tool", {}).get("finecode", {}).get("presets", []) + ) + presets_packages_names: list[str] = [] + for preset_def in presets_in_config: + try: + preset_package = preset_def.get("source") + except KeyError: + # workspace manager validates configuration and source should + # always exist, but still handle + raise FailedToGetDependencies(f"preset has no source: {preset_def}") + presets_packages_names.append(preset_package) + + # straightforward solution for now + deps_groups = project_raw_config.get("dependency-groups", {}) + env_raw_deps = deps_groups.get(env_name, []) + env_deps_config = ( + project_raw_config.get("tool", {}) + .get("finecode", {}) + .get("env", {}) + .get(env_name, {}) + .get("dependencies", {}) + ) + dependencies = [] + + try: + runner_dep = next( + dep + for dep in env_raw_deps + if isinstance(dep, str) + and dependency_config_utils.get_dependency_name(dep) + == "finecode_extension_runner" + ) + except StopIteration: + raise FailedToGetDependencies( + f"prepare_runners expects finecode_extension_runner dependency in each environment, but it was not found in {env_name}" + ) + + runner_dep_dict = dependency_config_utils.raw_dep_to_dep_dict( + raw_dep=runner_dep, env_deps_config=env_deps_config + ) + dependencies.append(runner_dep_dict) + + for preset_package in presets_packages_names: + try: + preset_dep = next( + dep + for dep in env_raw_deps + if isinstance(dep, str) + and dependency_config_utils.get_dependency_name(dep) == preset_package + ) + except StopIteration: + if env_name == "dev_no_runtime": + # all preset packages must be in 'dev_no_runtime' env + raise FailedToGetDependencies( + f"'{preset_package}' is used as preset source, but not declared in 'dev_no_runtime' dependency group" + ) + else: + continue + + preset_dep_dict = dependency_config_utils.raw_dep_to_dep_dict( + raw_dep=preset_dep, env_deps_config=env_deps_config + ) + dependencies.append(preset_dep_dict) + return dependencies diff --git a/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_runners_read_configs.py b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_runners_read_configs.py new file mode 100644 index 0000000..e9408b0 --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/action_handlers/prepare_runners_read_configs.py @@ -0,0 +1,73 @@ +import asyncio +import dataclasses +import pathlib +import shutil +import typing + +from finecode_extension_api import code_action +from finecode_extension_api.actions import prepare_runners as prepare_runners_action +from finecode_extension_api.interfaces import ( + iactionrunner, + ilogger, + iprojectinfoprovider, +) +from finecode_extension_runner.action_handlers import dependency_config_utils + + +@dataclasses.dataclass +class PrepareRunnersReadConfigsHandlerConfig(code_action.ActionHandlerConfig): ... + + +class PrepareRunnersReadConfigsHandler( + code_action.ActionHandler[ + prepare_runners_action.PrepareRunnersAction, + PrepareRunnersReadConfigsHandlerConfig, + ] +): + def __init__( + self, + action_runner: iactionrunner.IActionRunner, + project_info_provider: iprojectinfoprovider.IProjectInfoProvider, + logger: ilogger.ILogger, + ) -> None: + self.action_runner = action_runner + self.project_info_provider = project_info_provider + self.logger = logger + + async def run( + self, + payload: prepare_runners_action.PrepareRunnersRunPayload, + run_context: prepare_runners_action.PrepareRunnersRunContext, + ) -> prepare_runners_action.PrepareRunnersRunResult: + project_defs_pathes = set( + [env_info.project_def_path for env_info in payload.envs] + ) + raw_config_by_project_def_path: dict[pathlib.Path, dict[str, typing.Any]] = {} + + get_config_tasks: list[asyncio.Task] = [] + async with asyncio.TaskGroup() as tg: + for project_def_path in project_defs_pathes: + task = tg.create_task( + self.project_info_provider.get_project_raw_config(project_def_path) + ) + get_config_tasks.append(task) + + for idx, project_def_path in enumerate(project_defs_pathes): + project_raw_config = get_config_tasks[idx].result() + dependency_config_utils.make_project_config_pip_compatible( + project_raw_config, project_def_path + ) + raw_config_by_project_def_path[project_def_path] = project_raw_config + + for env_info in payload.envs: + run_context.project_def_path_by_venv_dir_path[env_info.venv_dir_path] = ( + env_info.project_def_path + ) + project_raw_config = raw_config_by_project_def_path[ + env_info.project_def_path + ] + run_context.project_def_by_venv_dir_path[env_info.venv_dir_path] = ( + project_raw_config + ) + + return prepare_runners_action.PrepareRunnersRunResult(errors=[]) diff --git a/src/finecode/extension_runner/action_utils.py b/finecode_extension_runner/src/finecode_extension_runner/action_utils.py similarity index 100% rename from src/finecode/extension_runner/action_utils.py rename to finecode_extension_runner/src/finecode_extension_runner/action_utils.py diff --git a/src/finecode/extension_runner/api.proto b/finecode_extension_runner/src/finecode_extension_runner/api.proto similarity index 93% rename from src/finecode/extension_runner/api.proto rename to finecode_extension_runner/src/finecode_extension_runner/api.proto index 67c7eb6..2a13af6 100644 --- a/src/finecode/extension_runner/api.proto +++ b/finecode_extension_runner/src/finecode_extension_runner/api.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package finecode.extension_runner; +package finecode_extension_runner; message UpdateConfigRequest { string working_dir = 1; diff --git a/src/finecode/extension_runner/app_dirs.py b/finecode_extension_runner/src/finecode_extension_runner/app_dirs.py similarity index 100% rename from src/finecode/extension_runner/app_dirs.py rename to finecode_extension_runner/src/finecode_extension_runner/app_dirs.py diff --git a/src/finecode/extension_runner/cli.py b/finecode_extension_runner/src/finecode_extension_runner/cli.py similarity index 59% rename from src/finecode/extension_runner/cli.py rename to finecode_extension_runner/src/finecode_extension_runner/cli.py index a24790d..83bebcb 100644 --- a/src/finecode/extension_runner/cli.py +++ b/finecode_extension_runner/src/finecode_extension_runner/cli.py @@ -1,14 +1,22 @@ import os +import sys +from importlib import metadata from pathlib import Path import click from loguru import logger -import finecode.extension_runner.start as runner_start -from finecode.extension_runner import global_state +import finecode_extension_runner.start as runner_start +from finecode_extension_runner import global_state -@click.command() +@click.group() +def main(): + """FineCode Extension Runner CLI""" + pass + + +@main.command() @click.option("--trace", "trace", is_flag=True, default=False) @click.option("--debug", "debug", is_flag=True, default=False) @click.option("--debug-port", "debug_port", type=int, default=5680) @@ -18,7 +26,10 @@ type=click.Path(exists=True, file_okay=False, resolve_path=True, path_type=Path), required=True, ) -def main(trace: bool, debug: bool, debug_port: int, project_path: Path): +@click.option("--env-name", "env_name", type=str) +def start( + trace: bool, debug: bool, debug_port: int, project_path: Path, env_name: str | None +): if debug is True: import debugpy @@ -30,13 +41,24 @@ def main(trace: bool, debug: bool, debug_port: int, project_path: Path): except Exception as e: logger.info(e) + if env_name is None: + click.echo("Environment name(--env-name) is required", err=True) + sys.exit(1) + global_state.log_level = "INFO" if trace is False else "TRACE" global_state.project_dir_path = project_path # asyncio.run(runner_start.start_runner()) # extension runner doesn't stop with async start after closing LS client(WM). Use # sync start until this problem is solved - runner_start.start_runner_sync() + runner_start.start_runner_sync(env_name) + + +@main.command() +def version(): + """Show version information""" + package_version = metadata.version("finecode_extension_runner") + click.echo(f"FineCode Extension Runner {package_version}") if __name__ == "__main__": diff --git a/src/finecode/extension_runner/context.py b/finecode_extension_runner/src/finecode_extension_runner/context.py similarity index 93% rename from src/finecode/extension_runner/context.py rename to finecode_extension_runner/src/finecode_extension_runner/context.py index a026ec0..baf4844 100644 --- a/src/finecode/extension_runner/context.py +++ b/finecode_extension_runner/src/finecode_extension_runner/context.py @@ -1,7 +1,7 @@ from dataclasses import dataclass, field -from finecode.extension_runner import domain from finecode_extension_api import code_action +from finecode_extension_runner import domain @dataclass diff --git a/src/finecode/workspace_manager/runner/__init__.py b/finecode_extension_runner/src/finecode_extension_runner/di/__init__.py similarity index 100% rename from src/finecode/workspace_manager/runner/__init__.py rename to finecode_extension_runner/src/finecode_extension_runner/di/__init__.py diff --git a/finecode_extension_runner/src/finecode_extension_runner/di/_state.py b/finecode_extension_runner/src/finecode_extension_runner/di/_state.py new file mode 100644 index 0000000..4ef45f9 --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/di/_state.py @@ -0,0 +1,4 @@ +import typing + +container: dict[str, typing.Any] = {} +factories: dict[str, typing.Callable] = {} diff --git a/finecode_extension_runner/src/finecode_extension_runner/di/bootstrap.py b/finecode_extension_runner/src/finecode_extension_runner/di/bootstrap.py new file mode 100644 index 0000000..45d2cfd --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/di/bootstrap.py @@ -0,0 +1,119 @@ +import functools +import pathlib +from typing import Any, Awaitable, Callable, Type, TypeVar + +try: + import fine_python_ast +except ImportError: + fine_python_ast = None + +try: + import fine_python_mypy +except ImportError: + fine_python_mypy = None + +from finecode_extension_api import code_action +from finecode_extension_api.interfaces import ( + iactionrunner, + icache, + icommandrunner, + ifilemanager, + ilogger, + iprojectinfoprovider, +) +from finecode_extension_runner import global_state, schemas +from finecode_extension_runner._services import run_action +from finecode_extension_runner.di import _state +from finecode_extension_runner.impls import ( + action_runner, + command_runner, + file_manager, + inmemory_cache, + loguru_logger, + project_info_provider, +) + + +def bootstrap( + get_document_func: Callable, + save_document_func: Callable, + project_def_path_getter: Callable[[], pathlib.Path], + project_raw_config_getter: Callable[[str], Awaitable[dict[str, Any]]], +): + # logger_instance = loguru_logger.LoguruLogger() + logger_instance = loguru_logger.get_logger() + command_runner_instance = command_runner.CommandRunner(logger=logger_instance) + file_manager_instance = file_manager.FileManager( + docs_owned_by_client=global_state.runner_context.docs_owned_by_client, + get_document_func=get_document_func, + save_document_func=save_document_func, + logger=logger_instance, + ) + cache_instance = inmemory_cache.InMemoryCache( + file_manager=file_manager_instance, logger=logger_instance + ) + action_runner_instance = action_runner.ActionRunner( + internal_service_func=run_action_wrapper + ) + _state.container[ilogger.ILogger] = logger_instance + _state.container[icommandrunner.ICommandRunner] = command_runner_instance + _state.container[ifilemanager.IFileManager] = file_manager_instance + _state.container[icache.ICache] = cache_instance + _state.container[iactionrunner.IActionRunner] = action_runner_instance + + if fine_python_ast is not None: + _state.factories[fine_python_ast.IPythonSingleAstProvider] = ( + python_single_ast_provider_factory + ) + if fine_python_mypy is not None: + _state.factories[fine_python_mypy.IMypySingleAstProvider] = ( + mypy_single_ast_provider_factory + ) + _state.factories[iprojectinfoprovider.IProjectInfoProvider] = functools.partial( + project_info_provider_factory, + project_def_path_getter=project_def_path_getter, + project_raw_config_getter=project_raw_config_getter, + ) + + # TODO: parameters from config + + +async def run_action_wrapper( + action_name: str, payload: dict[str, Any] +) -> dict[str, Any]: + request = schemas.RunActionRequest(action_name=action_name, params=payload) + options = schemas.RunActionOptions(result_format="json") + + try: + response = await run_action.run_action(request=request, options=options) + except run_action.ActionFailedException as exception: + raise iactionrunner.ActionRunFailed(exception.message) + + return response.result + + +def python_single_ast_provider_factory(container): + return fine_python_ast.PythonSingleAstProvider( + file_manager=container[ifilemanager.IFileManager], + cache=container[icache.ICache], + logger=container[ilogger.ILogger], + ) + + +def mypy_single_ast_provider_factory(container): + return fine_python_mypy.MypySingleAstProvider( + file_manager=container[ifilemanager.IFileManager], + cache=container[icache.ICache], + logger=container[ilogger.ILogger], + ) + + +def project_info_provider_factory( + container, + project_def_path_getter: Callable[[], pathlib.Path], + project_raw_config_getter: Callable[[str], Awaitable[dict[str, Any]]], +): + return project_info_provider.ProjectInfoProvider( + project_def_path_getter=project_def_path_getter, + project_raw_config_getter=project_raw_config_getter, + ) diff --git a/finecode_extension_runner/src/finecode_extension_runner/di/resolver.py b/finecode_extension_runner/src/finecode_extension_runner/di/resolver.py new file mode 100644 index 0000000..f9d10e2 --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/di/resolver.py @@ -0,0 +1,24 @@ +from typing import Any, Callable, Type, TypeVar + +from finecode_extension_api import code_action + +from ._state import container, factories + +T = TypeVar("T") + + +def get_service_instance(service_type: Type[T]) -> T: + if service_type == code_action.ActionHandlerLifecycle: + return code_action.ActionHandlerLifecycle() + + # singletons + if service_type in container: + return container[service_type] + else: + if service_type in factories: + service_instance = factories[service_type](container) + else: + raise ValueError(f"No implementation found for {service_type}") + + container[service_type] = service_instance + return service_instance diff --git a/src/finecode/extension_runner/domain.py b/finecode_extension_runner/src/finecode_extension_runner/domain.py similarity index 93% rename from src/finecode/extension_runner/domain.py rename to finecode_extension_runner/src/finecode_extension_runner/domain.py index 46686a5..c422f5a 100644 --- a/src/finecode/extension_runner/domain.py +++ b/finecode_extension_runner/src/finecode_extension_runner/domain.py @@ -4,8 +4,8 @@ import typing from pathlib import Path -from finecode.extension_runner.impls import process_executor as process_executor_impl from finecode_extension_api import code_action +from finecode_extension_runner.impls import process_executor as process_executor_impl class Action: @@ -35,10 +35,12 @@ def __init__( name: str, path: Path, actions: dict[str, Action], + action_handler_configs: dict[str, dict[str, typing.Any]], ) -> None: self.name = name self.path = path self.actions = actions + self.action_handler_configs = action_handler_configs def __str__(self) -> str: return f'Project(name="{self.name}", path="{self.path}")' diff --git a/src/finecode/extension_runner/global_state.py b/finecode_extension_runner/src/finecode_extension_runner/global_state.py similarity index 85% rename from src/finecode/extension_runner/global_state.py rename to finecode_extension_runner/src/finecode_extension_runner/global_state.py index 0e012e9..6282cc7 100644 --- a/src/finecode/extension_runner/global_state.py +++ b/finecode_extension_runner/src/finecode_extension_runner/global_state.py @@ -1,7 +1,7 @@ from pathlib import Path from typing import Literal -import finecode.extension_runner.context as context +import finecode_extension_runner.context as context runner_context: context.RunnerContext | None = None # it's the same as `runner_context.project.path`, but it's available from the start of diff --git a/src/finecode/workspace_manager/utils/__init__.py b/finecode_extension_runner/src/finecode_extension_runner/impls/__init__.py similarity index 100% rename from src/finecode/workspace_manager/utils/__init__.py rename to finecode_extension_runner/src/finecode_extension_runner/impls/__init__.py diff --git a/finecode_extension_runner/src/finecode_extension_runner/impls/action_runner.py b/finecode_extension_runner/src/finecode_extension_runner/impls/action_runner.py new file mode 100644 index 0000000..1b39c80 --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/impls/action_runner.py @@ -0,0 +1,12 @@ +from pathlib import Path +from typing import Any, TypeAlias + +from finecode_extension_api.interfaces import iactionrunner + + +class ActionRunner(iactionrunner.IActionRunner): + def __init__(self, internal_service_func): + self._internal_service_func = internal_service_func + + async def run_action(self, name: str, payload: dict[str, Any]) -> dict[str, Any]: + return await self._internal_service_func(action_name=name, payload=payload) diff --git a/src/finecode/extension_runner/impls/command_runner.py b/finecode_extension_runner/src/finecode_extension_runner/impls/command_runner.py similarity index 100% rename from src/finecode/extension_runner/impls/command_runner.py rename to finecode_extension_runner/src/finecode_extension_runner/impls/command_runner.py diff --git a/src/finecode/extension_runner/impls/file_manager.py b/finecode_extension_runner/src/finecode_extension_runner/impls/file_manager.py similarity index 86% rename from src/finecode/extension_runner/impls/file_manager.py rename to finecode_extension_runner/src/finecode_extension_runner/impls/file_manager.py index e9d4883..70ee436 100644 --- a/src/finecode/extension_runner/impls/file_manager.py +++ b/finecode_extension_runner/src/finecode_extension_runner/impls/file_manager.py @@ -1,10 +1,10 @@ import hashlib +import shutil from pathlib import Path from typing import Callable -from finecode import pygls_types_utils -from finecode.extension_runner import domain from finecode_extension_api.interfaces import ifilemanager, ilogger +from finecode_extension_runner import domain class FileManager(ifilemanager.IFileManager): @@ -37,7 +37,7 @@ async def get_content(self, file_path: Path) -> str: return file_content async def get_file_version(self, file_path: Path) -> str: - file_uri = pygls_types_utils.path_to_uri_str(file_path) + file_uri = path_to_uri_str(file_path) file_version: str = "" if file_uri in self.docs_owned_by_client: @@ -68,13 +68,22 @@ async def get_file_version(self, file_path: Path) -> str: return file_version async def save_file(self, file_path: Path, file_content: str) -> None: - file_uri = pygls_types_utils.path_to_uri_str(file_path) + file_uri = path_to_uri_str(file_path) if file_uri in self.docs_owned_by_client: await self.save_document_func(file_uri, file_content) else: with open(file_path, "w") as f: f.write(file_content) + async def create_dir( + self, dir_path: Path, create_parents: bool = True, exist_ok: bool = True + ): + # currently only local file system is supported + dir_path.mkdir(parents=create_parents, exist_ok=exist_ok) + + async def remove_dir(self, dir_path: Path) -> None: + shutil.rmtree(dir_path) + # helper methods def read_content_file_from_fs(self, file_path: Path) -> str: # don't use this method directly, use `get_content` instead @@ -92,3 +101,7 @@ def get_hash_of_file_from_fs(self, file_path: Path) -> str: file_version = hashlib.file_digest(f, "sha256").hexdigest() return file_version + + +def path_to_uri_str(path: Path) -> str: + return f"file://{path.as_posix()}" diff --git a/src/finecode/extension_runner/impls/inmemory_cache.py b/finecode_extension_runner/src/finecode_extension_runner/impls/inmemory_cache.py similarity index 100% rename from src/finecode/extension_runner/impls/inmemory_cache.py rename to finecode_extension_runner/src/finecode_extension_runner/impls/inmemory_cache.py diff --git a/src/finecode/extension_runner/impls/loguru_logger.py b/finecode_extension_runner/src/finecode_extension_runner/impls/loguru_logger.py similarity index 96% rename from src/finecode/extension_runner/impls/loguru_logger.py rename to finecode_extension_runner/src/finecode_extension_runner/impls/loguru_logger.py index db07c77..c5536f3 100644 --- a/src/finecode/extension_runner/impls/loguru_logger.py +++ b/finecode_extension_runner/src/finecode_extension_runner/impls/loguru_logger.py @@ -7,7 +7,7 @@ # else: # from typing import override -# from finecode.extension_runner.interfaces import ilogger +# from finecode_extension_runner.interfaces import ilogger # class LoguruLogger(ilogger.ILogger): diff --git a/src/finecode/extension_runner/impls/process_executor.py b/finecode_extension_runner/src/finecode_extension_runner/impls/process_executor.py similarity index 98% rename from src/finecode/extension_runner/impls/process_executor.py rename to finecode_extension_runner/src/finecode_extension_runner/impls/process_executor.py index aad6aff..1b7434e 100644 --- a/src/finecode/extension_runner/impls/process_executor.py +++ b/finecode_extension_runner/src/finecode_extension_runner/impls/process_executor.py @@ -26,7 +26,6 @@ def activate(self) -> collections.abc.Iterator[None]: try: yield except Exception as exc: - logger.exception(exc) raise exc finally: if self._py_process_executor is not None: diff --git a/finecode_extension_runner/src/finecode_extension_runner/impls/project_info_provider.py b/finecode_extension_runner/src/finecode_extension_runner/impls/project_info_provider.py new file mode 100644 index 0000000..b7eee0c --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/impls/project_info_provider.py @@ -0,0 +1,26 @@ +import pathlib +from typing import Any, Awaitable, Callable + +from finecode_extension_api.interfaces import iprojectinfoprovider + + +class ProjectInfoProvider(iprojectinfoprovider.IProjectInfoProvider): + def __init__( + self, + project_def_path_getter: Callable[[], pathlib.Path], + project_raw_config_getter: Callable[[str], Awaitable[dict[str, Any]]], + ) -> None: + self.project_def_path_getter = project_def_path_getter + self.project_raw_config_getter = project_raw_config_getter + + def get_current_project_def_path(self) -> pathlib.Path: + return self.project_def_path_getter() + + async def get_project_raw_config( + self, project_def_path: pathlib.Path + ) -> dict[str, Any]: + return await self.project_raw_config_getter(str(project_def_path)) + + async def get_current_project_raw_config(self) -> dict[str, Any]: + current_project_path = self.get_current_project_def_path() + return await self.get_project_raw_config(project_def_path=current_project_path) diff --git a/src/finecode/logs.py b/finecode_extension_runner/src/finecode_extension_runner/logs.py similarity index 94% rename from src/finecode/logs.py rename to finecode_extension_runner/src/finecode_extension_runner/logs.py index 22dbdd6..a9ea3dd 100644 --- a/src/finecode/logs.py +++ b/finecode_extension_runner/src/finecode_extension_runner/logs.py @@ -68,3 +68,6 @@ def set_log_level_for_group(group: str, level: LogLevel | None): def reset_log_level_for_group(group: str): if group in log_level_by_group: del log_level_by_group[group] + + +__all__ = ["save_logs_to_file", "set_log_level_for_group", "reset_log_level_for_group"] diff --git a/src/finecode/extension_runner/lsp_server.py b/finecode_extension_runner/src/finecode_extension_runner/lsp_server.py similarity index 57% rename from src/finecode/extension_runner/lsp_server.py rename to finecode_extension_runner/src/finecode_extension_runner/lsp_server.py index 9b48ca0..e6328d1 100644 --- a/src/finecode/extension_runner/lsp_server.py +++ b/finecode_extension_runner/src/finecode_extension_runner/lsp_server.py @@ -6,16 +6,21 @@ from __future__ import annotations import atexit +import dataclasses +import functools import json +import pathlib import time +import typing import pygls.exceptions as pygls_exceptions from loguru import logger from lsprotocol import types from pygls.lsp import server as lsp_server -from finecode.extension_runner import domain, schemas, services from finecode_extension_api import code_action +from finecode_extension_runner import domain, schemas, services +from finecode_extension_runner._services import run_action as run_action_service class CustomLanguageServer(lsp_server.LanguageServer): @@ -62,64 +67,15 @@ def on_process_exit(): atexit.register(on_process_exit) - async def document_requester(uri: str): - try: - document = await server.protocol.send_request_async( - "documents/get", params={"uri": uri} - ) - except pygls_exceptions.JsonRpcInternalError as error: - if error.message == "Exception: Document is not opened": - raise domain.TextDocumentNotOpened() - else: - raise error - - return domain.TextDocumentInfo( - uri=document.uri, version=document.version, text=document.text - ) - - async def document_saver(uri: str, content: str): - document = await server.protocol.send_request_async( - "documents/get", params={"uri": uri} - ) - document_lines = document.text.split("\n") - params = types.ApplyWorkspaceEditParams( - edit=types.WorkspaceEdit( - # dict seems to be incorrectly unstructured on client(pygls issue?) - # use document_changes instead of changes - document_changes=[ - types.TextDocumentEdit( - text_document=types.OptionalVersionedTextDocumentIdentifier( - uri=uri - ), - edits=[ - types.TextEdit( - range=types.Range( - start=types.Position(line=0, character=0), - end=types.Position( - line=len(document_lines), - character=len(document_lines[-1]), - ), - ), - new_text=content, - ) - ], - ) - ] - ) - ) - await server.workspace_apply_edit_async(params) - def send_partial_result( token: int | str, partial_result: code_action.RunActionResult ) -> None: logger.debug(f"Send partial result for {token}") - server.progress( - types.ProgressParams(token=token, value=partial_result.model_dump_json()) - ) + partial_result_dict = dataclasses.asdict(partial_result) + partial_result_json = json.dumps(partial_result_dict) + server.progress(types.ProgressParams(token=token, value=partial_result_json)) - services.document_requester = document_requester - services.document_saver = document_saver - services.set_partial_result_sender(send_partial_result) + run_action_service.set_partial_result_sender(send_partial_result) return server @@ -147,12 +103,76 @@ def _document_did_close( services.document_did_close(params.text_document.uri) +async def document_requester(server: lsp_server.LanguageServer, uri: str): + try: + document = await server.protocol.send_request_async( + "documents/get", params={"uri": uri} + ) + except pygls_exceptions.JsonRpcInternalError as error: + if error.message == "Exception: Document is not opened": + raise domain.TextDocumentNotOpened() + else: + raise error + + return domain.TextDocumentInfo( + uri=document.uri, version=document.version, text=document.text + ) + + +async def document_saver(server: lsp_server.LanguageServer, uri: str, content: str): + document = await server.protocol.send_request_async( + "documents/get", params={"uri": uri} + ) + document_lines = document.text.split("\n") + params = types.ApplyWorkspaceEditParams( + edit=types.WorkspaceEdit( + # dict seems to be incorrectly unstructured on client(pygls issue?) + # use document_changes instead of changes + document_changes=[ + types.TextDocumentEdit( + text_document=types.OptionalVersionedTextDocumentIdentifier( + uri=uri + ), + edits=[ + types.TextEdit( + range=types.Range( + start=types.Position(line=0, character=0), + end=types.Position( + line=len(document_lines), + character=len(document_lines[-1]), + ), + ), + new_text=content, + ) + ], + ) + ] + ) + ) + await server.workspace_apply_edit_async(params) + + +async def get_project_raw_config( + server: lsp_server.LanguageServer, project_def_path: str +) -> dict[str, typing.Any]: + try: + raw_config = await server.protocol.send_request_async( + "projects/getRawConfig", params={"projectDefPath": project_def_path} + ) + except pygls_exceptions.JsonRpcInternalError as error: + raise error + + return json.loads(raw_config.config) + + async def update_config(ls: lsp_server.LanguageServer, params): logger.trace(f"Update config: {params}") try: working_dir = params[0] project_name = params[1] - actions = params[2] + config = params[2] + actions = config["actions"] + action_handler_configs = config["action_handler_configs"] request = schemas.UpdateConfigRequest( working_dir=working_dir, @@ -173,28 +193,56 @@ async def update_config(ls: lsp_server.LanguageServer, params): ) for action in actions }, + action_handler_configs=action_handler_configs, + ) + response = await services.update_config( + request=request, + document_requester=functools.partial(document_requester, ls), + document_saver=functools.partial(document_saver, ls), + project_raw_config_getter=functools.partial(get_project_raw_config, ls), ) - response = await services.update_config(request=request) return response.to_dict() except Exception as e: logger.exception(f"Update config error: {e}") raise e +class CustomJSONEncoder(json.JSONEncoder): + # add support of serializing pathes to json.dumps + def default(self, obj): + if isinstance(obj, (pathlib.Path, pathlib.PosixPath, pathlib.WindowsPath)): + return str(obj) + return super().default(obj) + + async def run_action(ls: lsp_server.LanguageServer, params): logger.trace(f"Run action: {params[0]}") request = schemas.RunActionRequest(action_name=params[0], params=params[1]) options = schemas.RunActionOptions(**params[2] if params[2] is not None else {}) - # pygls sends uncatched exceptions(e.g. internal errors) to client. Log them as well + status: str = "success" + try: response = await services.run_action(request=request, options=options) - except Exception as e: - logger.exception(f"Run action error: {e}") - raise e + except Exception as exception: + if isinstance(exception, services.StopWithResponse): + status = "stopped" + response = exception.response + else: + error_msg = "" + if isinstance(exception, services.ActionFailedException): + logger.error(f"Run action failed: {exception.message}") + error_msg = exception.message + else: + logger.error("Unhandled exception in action run:") + logger.exception(exception) + error_msg = f"{type(exception)}: {str(exception)}" + return {"error": error_msg} + # dict key can be path, but pygls fails to handle slashes in dict keys, use strings # representation of result instead until the problem is properly solved - result_str = json.dumps(response.to_dict()["result"]) + result_str = json.dumps(response.to_dict()["result"], cls=CustomJSONEncoder) return { + "status": status, "result": result_str, "format": response.format, "return_code": response.return_code, @@ -209,5 +257,7 @@ async def reload_action(ls: lsp_server.LanguageServer, params): async def resolve_package_path(ls: lsp_server.LanguageServer, params): logger.trace(f"Resolve package path: {params}") + # TODO: handle properly ValueError result = services.resolve_package_path(params[0]) + logger.trace(f"Resolved {params[0]} to {result}") return {"packagePath": result} diff --git a/src/finecode/extension_runner/partial_result_sender.py b/finecode_extension_runner/src/finecode_extension_runner/partial_result_sender.py similarity index 100% rename from src/finecode/extension_runner/partial_result_sender.py rename to finecode_extension_runner/src/finecode_extension_runner/partial_result_sender.py diff --git a/src/finecode/extension_runner/project_dirs.py b/finecode_extension_runner/src/finecode_extension_runner/project_dirs.py similarity index 91% rename from src/finecode/extension_runner/project_dirs.py rename to finecode_extension_runner/src/finecode_extension_runner/project_dirs.py index b21bbd5..347cb40 100644 --- a/src/finecode/extension_runner/project_dirs.py +++ b/finecode_extension_runner/src/finecode_extension_runner/project_dirs.py @@ -2,7 +2,7 @@ import os from pathlib import Path -from finecode.extension_runner import app_dirs +from finecode_extension_runner import app_dirs def get_project_dir(project_path: Path) -> Path: diff --git a/finecode_extension_runner/src/finecode_extension_runner/py.typed b/finecode_extension_runner/src/finecode_extension_runner/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/src/finecode/extension_runner/run_utils.py b/finecode_extension_runner/src/finecode_extension_runner/run_utils.py similarity index 100% rename from src/finecode/extension_runner/run_utils.py rename to finecode_extension_runner/src/finecode_extension_runner/run_utils.py diff --git a/src/finecode/extension_runner/schemas.py b/finecode_extension_runner/src/finecode_extension_runner/schemas.py similarity index 95% rename from src/finecode/extension_runner/schemas.py rename to finecode_extension_runner/src/finecode_extension_runner/schemas.py index 2289a9f..71f7fc1 100644 --- a/src/finecode/extension_runner/schemas.py +++ b/finecode_extension_runner/src/finecode_extension_runner/schemas.py @@ -29,6 +29,7 @@ class UpdateConfigRequest(BaseSchema): working_dir: Path project_name: str actions: dict[str, Action] + action_handler_configs: dict[str, dict[str, Any]] @dataclass diff --git a/finecode_extension_runner/src/finecode_extension_runner/services.py b/finecode_extension_runner/src/finecode_extension_runner/services.py new file mode 100644 index 0000000..86bb2cf --- /dev/null +++ b/finecode_extension_runner/src/finecode_extension_runner/services.py @@ -0,0 +1,233 @@ +import asyncio +import collections.abc +import importlib +import inspect +import sys +import time +import types +import typing +from pathlib import Path + +from loguru import logger +from pydantic.dataclasses import dataclass as pydantic_dataclass + +from finecode_extension_api import code_action, textstyler +from finecode_extension_runner import ( + context, + domain, + global_state, + project_dirs, + run_utils, + schemas, +) +from finecode_extension_runner._services import run_action as run_action_module +from finecode_extension_runner._services.run_action import ( + ActionFailedException, + StopWithResponse, + run_action, +) +from finecode_extension_runner.di import bootstrap as di_bootstrap + + +async def update_config( + request: schemas.UpdateConfigRequest, + document_requester: typing.Callable, + document_saver: typing.Callable, + project_raw_config_getter: typing.Callable[ + [str], typing.Awaitable[dict[str, typing.Any]] + ], +) -> schemas.UpdateConfigResponse: + project_path = Path(request.working_dir) + + actions: dict[str, domain.Action] = {} + for action_name, action_schema_obj in request.actions.items(): + handlers: list[domain.ActionHandler] = [] + for handler_obj in action_schema_obj.handlers: + handlers.append( + domain.ActionHandler( + name=handler_obj.name, + source=handler_obj.source, + config=handler_obj.config, + ) + ) + action = domain.Action( + name=action_name, + config=action_schema_obj.config, + handlers=handlers, + source=action_schema_obj.source, + ) + actions[action_name] = action + + global_state.runner_context = context.RunnerContext( + project=domain.Project( + name=request.project_name, + path=project_path, + actions=actions, + action_handler_configs=request.action_handler_configs, + ), + ) + + # currently update_config is called only once directly after runner start. So we can + # bootstrap here. Should be changed after adding updating configuration on the fly. + def project_def_path_getter() -> Path: + assert global_state.runner_context is not None + return global_state.runner_context.project.path + + di_bootstrap.bootstrap( + get_document_func=document_requester, + save_document_func=document_saver, + project_def_path_getter=project_def_path_getter, + project_raw_config_getter=project_raw_config_getter, + ) + + return schemas.UpdateConfigResponse() + + +def reload_action(action_name: str) -> None: + if global_state.runner_context is None: + # TODO: raise error + return + + project_def = global_state.runner_context.project + + try: + action_obj = project_def.actions[action_name] + except KeyError: + available_actions_str = ",".join( + [action_name for action_name in project_def.actions] + ) + logger.warning( + f"Action {action_name} not found." + f" Available actions: {available_actions_str}" + ) + # TODO: raise error + return + + actions_to_remove: list[str] = [ + action_name, + *[handler.name for handler in action_obj.handlers], + ] + + for _action_name in actions_to_remove: + try: + del global_state.runner_context.action_handlers_instances_by_name[ + _action_name + ] + logger.trace(f"Removed '{_action_name}' instance from cache") + except KeyError: + logger.info( + f"Tried to reload action '{_action_name}', but it was not found" + ) + + if ( + _action_name + in global_state.runner_context.action_handlers_exec_info_by_name + ): + shutdown_action_handler( + action_handler_name=_action_name, + exec_info=global_state.runner_context.action_handlers_exec_info_by_name[ + _action_name + ], + ) + + try: + action_obj = project_def.actions[action_name] + except KeyError: + logger.warning(f"Definition of action {action_name} not found") + continue + + action_source = action_obj.source + if action_source is None: + continue + action_package = action_source.split(".")[0] + + loaded_package_modules = dict( + [ + (key, value) + for key, value in sys.modules.items() + if key.startswith(action_package) + and isinstance(value, types.ModuleType) + ] + ) + + # delete references to these loaded modules from sys.modules + for key in loaded_package_modules: + del sys.modules[key] + + logger.trace(f"Remove modules of package '{action_package}' from cache") + + +def resolve_package_path(package_name: str) -> str: + try: + package_path = importlib.util.find_spec( + package_name + ).submodule_search_locations[0] + except Exception: + raise ValueError(f"Cannot find package {package_name}") + + return package_path + + +def document_did_open(document_uri: str) -> None: + global_state.runner_context.docs_owned_by_client.append(document_uri) + + +def document_did_close(document_uri: str) -> None: + global_state.runner_context.docs_owned_by_client.remove(document_uri) + + +def shutdown_action_handler( + action_handler_name: str, exec_info: domain.ActionHandlerExecInfo +) -> None: + # action handler exec info expected to exist in runner_context + if exec_info.status == domain.ActionHandlerExecInfoStatus.SHUTDOWN: + return + + if ( + exec_info.lifecycle is not None + and exec_info.lifecycle.on_shutdown_callable is not None + ): + logger.trace(f"Shutdown {action_handler_name} action handler") + try: + exec_info.lifecycle.on_shutdown_callable() + except Exception as e: + logger.error(f"Failed to shutdown action {action_handler_name}: {e}") + exec_info.status = domain.ActionHandlerExecInfoStatus.SHUTDOWN + + +def shutdown_all_action_handlers() -> None: + logger.trace("Shutdown all action handlers") + for ( + action_handler_name, + exec_info, + ) in global_state.runner_context.action_handlers_exec_info_by_name.items(): + shutdown_action_handler( + action_handler_name=action_handler_name, exec_info=exec_info + ) + + +def exit_action_handler( + action_handler_name: str, exec_info: domain.ActionHandlerExecInfo +) -> None: + # action handler exec info expected to exist in runner_context + if ( + exec_info.lifecycle is not None + and exec_info.lifecycle.on_exit_callable is not None + ): + logger.trace(f"Exit {action_handler_name} action handler") + try: + exec_info.lifecycle.on_exit_callable() + except Exception as e: + logger.error(f"Failed to exit action {action_handler_name}: {e}") + + +def exit_all_action_handlers() -> None: + logger.trace("Exit all action handlers") + for ( + action_handler_name, + exec_info, + ) in global_state.runner_context.action_handlers_exec_info_by_name.items(): + exit_action_handler( + action_handler_name=action_handler_name, exec_info=exec_info + ) + global_state.runner_context.action_handlers_exec_info_by_name = {} diff --git a/src/finecode/extension_runner/start.py b/finecode_extension_runner/src/finecode_extension_runner/start.py similarity index 86% rename from src/finecode/extension_runner/start.py rename to finecode_extension_runner/src/finecode_extension_runner/start.py index 6a7e967..904868a 100644 --- a/src/finecode/extension_runner/start.py +++ b/finecode_extension_runner/src/finecode_extension_runner/start.py @@ -4,10 +4,9 @@ from loguru import logger -import finecode.extension_runner.global_state as global_state -import finecode.extension_runner.lsp_server as extension_runner_lsp -import finecode.extension_runner.project_dirs as project_dirs -from finecode import logs +import finecode_extension_runner.global_state as global_state +import finecode_extension_runner.lsp_server as extension_runner_lsp +from finecode_extension_runner import logs # import finecode.pygls_server_utils as pygls_server_utils @@ -54,16 +53,20 @@ # await pygls_server_utils.start_io_async(server) -def start_runner_sync(): - project_log_dir_path = project_dirs.get_project_dir(global_state.project_dir_path) +def start_runner_sync(env_name: str) -> None: logger.remove() # disable logging raw messages # TODO: make configurable logger.configure(activation=[("pygls.protocol.json_rpc", False)]) # ~~extension runner communicates with workspace manager with tcp, we can print logs # to stdout as well~~. See README.md + assert global_state.project_dir_path is not None logs.save_logs_to_file( - file_path=project_log_dir_path / "execution.log", + file_path=global_state.project_dir_path + / ".venvs" + / env_name + / "logs" + / "runner.log", log_level=global_state.log_level, stdout=False, ) @@ -94,10 +97,10 @@ def emit(self, record: logging.LogRecord) -> None: # TODO: make configurable logs.set_log_level_for_group( - "finecode.extension_runner.impls.file_manager", logs.LogLevel.WARNING + "finecode_extension_runner.impls.file_manager", logs.LogLevel.WARNING ) logs.set_log_level_for_group( - "finecode.extension_runner.impls.inmemory_cache", logs.LogLevel.WARNING + "finecode_extension_runner.impls.inmemory_cache", logs.LogLevel.WARNING ) logger.info(f"Python executable: {sys.executable}") diff --git a/finecode_extension_runner/src/finecode_extension_runner/utils/__init__.py b/finecode_extension_runner/src/finecode_extension_runner/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 63d038e..0000000 --- a/poetry.lock +++ /dev/null @@ -1,1196 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "anyio" -version = "4.9.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"}, - {file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"}, -] - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" -typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} - -[package.extras] -doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] -trio = ["trio (>=0.26.1)"] - -[[package]] -name = "attrs" -version = "25.3.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, - {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, -] - -[package.extras] -benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] - -[[package]] -name = "black" -version = "25.1.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, - {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, - {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, - {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, - {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, - {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, - {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, - {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, - {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, - {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, - {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, - {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, - {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, - {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, - {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, - {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, - {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, - {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, - {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, - {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, - {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, - {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "cattrs" -version = "24.1.3" -description = "Composable complex class support for attrs and dataclasses." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "cattrs-24.1.3-py3-none-any.whl", hash = "sha256:adf957dddd26840f27ffbd060a6c4dd3b2192c5b7c2c0525ef1bd8131d8a83f5"}, - {file = "cattrs-24.1.3.tar.gz", hash = "sha256:981a6ef05875b5bb0c7fb68885546186d306f10f0f6718fe9b96c226e68821ff"}, -] - -[package.dependencies] -attrs = ">=23.1.0" - -[package.extras] -bson = ["pymongo (>=4.4.0)"] -cbor2 = ["cbor2 (>=5.4.6)"] -msgpack = ["msgpack (>=1.0.5)"] -msgspec = ["msgspec (>=0.18.5) ; implementation_name == \"cpython\""] -orjson = ["orjson (>=3.9.2) ; implementation_name == \"cpython\""] -pyyaml = ["pyyaml (>=6.0)"] -tomlkit = ["tomlkit (>=0.11.8)"] -ujson = ["ujson (>=5.7.0)"] - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -markers = {main = "sys_platform == \"win32\" or platform_system == \"Windows\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\""} - -[[package]] -name = "debugpy" -version = "1.8.14" -description = "An implementation of the Debug Adapter Protocol for Python" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "debugpy-1.8.14-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:93fee753097e85623cab1c0e6a68c76308cd9f13ffdf44127e6fab4fbf024339"}, - {file = "debugpy-1.8.14-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d937d93ae4fa51cdc94d3e865f535f185d5f9748efb41d0d49e33bf3365bd79"}, - {file = "debugpy-1.8.14-cp310-cp310-win32.whl", hash = "sha256:c442f20577b38cc7a9aafecffe1094f78f07fb8423c3dddb384e6b8f49fd2987"}, - {file = "debugpy-1.8.14-cp310-cp310-win_amd64.whl", hash = "sha256:f117dedda6d969c5c9483e23f573b38f4e39412845c7bc487b6f2648df30fe84"}, - {file = "debugpy-1.8.14-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:1b2ac8c13b2645e0b1eaf30e816404990fbdb168e193322be8f545e8c01644a9"}, - {file = "debugpy-1.8.14-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf431c343a99384ac7eab2f763980724834f933a271e90496944195318c619e2"}, - {file = "debugpy-1.8.14-cp311-cp311-win32.whl", hash = "sha256:c99295c76161ad8d507b413cd33422d7c542889fbb73035889420ac1fad354f2"}, - {file = "debugpy-1.8.14-cp311-cp311-win_amd64.whl", hash = "sha256:7816acea4a46d7e4e50ad8d09d963a680ecc814ae31cdef3622eb05ccacf7b01"}, - {file = "debugpy-1.8.14-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:8899c17920d089cfa23e6005ad9f22582fd86f144b23acb9feeda59e84405b84"}, - {file = "debugpy-1.8.14-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6bb5c0dcf80ad5dbc7b7d6eac484e2af34bdacdf81df09b6a3e62792b722826"}, - {file = "debugpy-1.8.14-cp312-cp312-win32.whl", hash = "sha256:281d44d248a0e1791ad0eafdbbd2912ff0de9eec48022a5bfbc332957487ed3f"}, - {file = "debugpy-1.8.14-cp312-cp312-win_amd64.whl", hash = "sha256:5aa56ef8538893e4502a7d79047fe39b1dae08d9ae257074c6464a7b290b806f"}, - {file = "debugpy-1.8.14-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:329a15d0660ee09fec6786acdb6e0443d595f64f5d096fc3e3ccf09a4259033f"}, - {file = "debugpy-1.8.14-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f920c7f9af409d90f5fd26e313e119d908b0dd2952c2393cd3247a462331f15"}, - {file = "debugpy-1.8.14-cp313-cp313-win32.whl", hash = "sha256:3784ec6e8600c66cbdd4ca2726c72d8ca781e94bce2f396cc606d458146f8f4e"}, - {file = "debugpy-1.8.14-cp313-cp313-win_amd64.whl", hash = "sha256:684eaf43c95a3ec39a96f1f5195a7ff3d4144e4a18d69bb66beeb1a6de605d6e"}, - {file = "debugpy-1.8.14-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:d5582bcbe42917bc6bbe5c12db1bffdf21f6bfc28d4554b738bf08d50dc0c8c3"}, - {file = "debugpy-1.8.14-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5349b7c3735b766a281873fbe32ca9cca343d4cc11ba4a743f84cb854339ff35"}, - {file = "debugpy-1.8.14-cp38-cp38-win32.whl", hash = "sha256:7118d462fe9724c887d355eef395fae68bc764fd862cdca94e70dcb9ade8a23d"}, - {file = "debugpy-1.8.14-cp38-cp38-win_amd64.whl", hash = "sha256:d235e4fa78af2de4e5609073972700523e372cf5601742449970110d565ca28c"}, - {file = "debugpy-1.8.14-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:413512d35ff52c2fb0fd2d65e69f373ffd24f0ecb1fac514c04a668599c5ce7f"}, - {file = "debugpy-1.8.14-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c9156f7524a0d70b7a7e22b2e311d8ba76a15496fb00730e46dcdeedb9e1eea"}, - {file = "debugpy-1.8.14-cp39-cp39-win32.whl", hash = "sha256:b44985f97cc3dd9d52c42eb59ee9d7ee0c4e7ecd62bca704891f997de4cef23d"}, - {file = "debugpy-1.8.14-cp39-cp39-win_amd64.whl", hash = "sha256:b1528cfee6c1b1c698eb10b6b096c598738a8238822d218173d21c3086de8123"}, - {file = "debugpy-1.8.14-py2.py3-none-any.whl", hash = "sha256:5cd9a579d553b6cb9759a7908a41988ee6280b961f24f63336835d9418216a20"}, - {file = "debugpy-1.8.14.tar.gz", hash = "sha256:7cd287184318416850aa8b60ac90105837bb1e59531898c07569d197d2ed5322"}, -] - -[[package]] -name = "fine-python-aksem" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_module_exports = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_module_exports"} - -[package.source] -type = "git" -url = "https://github.com/Aksem/fine_python_aksem.git" -reference = "HEAD" -resolved_reference = "56ce22c3fb1228a6e85d1a8727a0fa74787608d9" - -[[package]] -name = "fine-python-ast" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "85ba26049dba2d4792f6e9d5370a1f5eef992ec8" -subdirectory = "extensions/fine_python_ast" - -[[package]] -name = "fine-python-black" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -black = ">=25.1.0,<26.0.0" -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "85ba26049dba2d4792f6e9d5370a1f5eef992ec8" -subdirectory = "extensions/fine_python_black" - -[[package]] -name = "fine-python-flake8" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_ast = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_ast"} -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -flake8 = ">=7.1.2,<8.0.0" -types-flake8 = ">=7.1.0.20241020,<8.0.0.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "85ba26049dba2d4792f6e9d5370a1f5eef992ec8" -subdirectory = "extensions/fine_python_flake8" - -[[package]] -name = "fine-python-format" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_black = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_black"} -fine_python_isort = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_isort"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "85ba26049dba2d4792f6e9d5370a1f5eef992ec8" -subdirectory = "presets/fine_python_format" - -[[package]] -name = "fine-python-import-linter" -version = "0.1.0" -description = "" -optional = false -python-versions = ">= 3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -import-linter = ">=2.1,<3.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "85ba26049dba2d4792f6e9d5370a1f5eef992ec8" -subdirectory = "extensions/fine_python_import_linter" - -[[package]] -name = "fine-python-isort" -version = "0.1.0" -description = "" -optional = false -python-versions = ">= 3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -isort = ">=5.13,<6" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "85ba26049dba2d4792f6e9d5370a1f5eef992ec8" -subdirectory = "extensions/fine_python_isort" - -[[package]] -name = "fine-python-lint" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_flake8 = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_flake8"} -fine_python_mypy = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_mypy"} -flake8-bugbear = ">=24.12.12,<25.0.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "85ba26049dba2d4792f6e9d5370a1f5eef992ec8" -subdirectory = "presets/fine_python_lint" - -[[package]] -name = "fine-python-module-exports" -version = "0.1.0" -description = "" -optional = false -python-versions = ">= 3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_ast = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_ast"} -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "85ba26049dba2d4792f6e9d5370a1f5eef992ec8" -subdirectory = "extensions/fine_python_module_exports" - -[[package]] -name = "fine-python-mypy" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -mypy = ">=1.15,<2.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "85ba26049dba2d4792f6e9d5370a1f5eef992ec8" -subdirectory = "extensions/fine_python_mypy" - -[[package]] -name = "fine-python-recommended" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_format = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_format"} -fine_python_lint = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_lint"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "85ba26049dba2d4792f6e9d5370a1f5eef992ec8" -subdirectory = "presets/fine_python_recommended" - -[[package]] -name = "finecode-dev-common-preset" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = true - -[package.dependencies] -fine_python_aksem = {git = "https://github.com/Aksem/fine_python_aksem.git"} -fine_python_recommended = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_recommended"} - -[package.source] -type = "directory" -url = "finecode_dev_common_preset" - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "finecode_extension_api-0.1.0-py3-none-any.whl", hash = "sha256:55d4448a1a2f7224c3fdf05879fa9782246c0a85dc1dfb17543374fd808c2b5b"}, - {file = "finecode_extension_api-0.1.0.tar.gz", hash = "sha256:dee16c180e4cd318f71bf7a94b6ae425667153f8fb62630ab60db9b034f45595"}, -] - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[[package]] -name = "flake8" -version = "7.2.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343"}, - {file = "flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.13.0,<2.14.0" -pyflakes = ">=3.3.0,<3.4.0" - -[[package]] -name = "flake8-bugbear" -version = "24.12.12" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -optional = false -python-versions = ">=3.8.1" -groups = ["dev"] -files = [ - {file = "flake8_bugbear-24.12.12-py3-none-any.whl", hash = "sha256:1b6967436f65ca22a42e5373aaa6f2d87966ade9aa38d4baf2a1be550767545e"}, - {file = "flake8_bugbear-24.12.12.tar.gz", hash = "sha256:46273cef0a6b6ff48ca2d69e472f41420a42a46e24b2a8972e4f0d6733d12a64"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -flake8 = ">=6.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] - -[[package]] -name = "grimp" -version = "3.9" -description = "Builds a queryable graph of the imports within one or more Python packages." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "grimp-3.9-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:febc16712658e4eed18a8f313036165eef33dabad65afde01c1da0429923f229"}, - {file = "grimp-3.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6b79782e4fad92ee0375ac20c086d7e32e23d880ff70541295da4fba07336486"}, - {file = "grimp-3.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dd8480adcd5241ffb013be922885b87de2fc7d834cdba1cc1d65f2c378bd282"}, - {file = "grimp-3.9-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc5860e9ad17f8538bb2064aed86df27058187e554f21ecc79b3f5ae7bf5f919"}, - {file = "grimp-3.9-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dca743dad74db046a1104f53d83d7297eb14990d0ba4c8a548c493145cc158bc"}, - {file = "grimp-3.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9886231877cda72aba4c4975d819d79f149e0edb22fd3f55ed5d5f89cb3ab28e"}, - {file = "grimp-3.9-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f80f7bf293c552edf1e48dcc7a4339532e604357b22b2ee1d55d08ae1ff2a811"}, - {file = "grimp-3.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb8bb74b38727a8928cfbfa670632c1f27cb97350348f954e318243a785f7a51"}, - {file = "grimp-3.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9fec4ca6a9cde9c6bc2c565243ec4294f6dea65da34c9af6b3d2725d0e6e055e"}, - {file = "grimp-3.9-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:03e99fed9ac98f732bfa528eeed76643013d8278eb62a271d841fadbde408252"}, - {file = "grimp-3.9-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b391fe8379fade735c21a016fd22eafb85cd65c7962e8bed176dc9c2ad5a169c"}, - {file = "grimp-3.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7f2af0715304971798241353a3e6c5cc64339a4871dd7b33372c810e5c7c7251"}, - {file = "grimp-3.9-cp310-cp310-win32.whl", hash = "sha256:4db8ac24b52e0859ac47ee2c6aa1b40323774078dbc22193699b3ad7d2bb1bd2"}, - {file = "grimp-3.9-cp310-cp310-win_amd64.whl", hash = "sha256:75ca679e9d341f31af7af6b02dcb1069bc08f3746416c7d86508073254714ff4"}, - {file = "grimp-3.9-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f28984e7b0be7c820cb41bf6fb05d707567cc892e84ca5cd21603c57e86627dd"}, - {file = "grimp-3.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:21a03a6b1c682f98d59971f10152d936fe4def0ac48109fd72d111a024588c7a"}, - {file = "grimp-3.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae8ce8ce5535c6bd50d4ce10747afc8f3d6d98b1c25c66856219bbeae82f3156"}, - {file = "grimp-3.9-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3e26ed94b20b2991bc0742ab468d40bff0e33619cf506ecb2ec15dd8baa1094d"}, - {file = "grimp-3.9-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6efe43e54753edca1705bf2d002e0c40e86402c19cd4ea66fb71e1bb628e8da"}, - {file = "grimp-3.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83b2354e90b57ea3335381df78ffe0d653f68a7a9e6fcf382f157ad9558d778"}, - {file = "grimp-3.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:465b6814c3e94081e9b9491975d8f14583ff1b2712e9ee2c7a88d165fece33ab"}, - {file = "grimp-3.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f7d4289c3dd7fdd515abf7ad7125c405367edbee6e286f29d5176b4278a232d"}, - {file = "grimp-3.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3de8685aefa3de3c966cebcbd660cbbdb10f890b0b11746adf730b5dc738b35d"}, - {file = "grimp-3.9-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:aec648946dd9f9cc154aa750b6875e1e6bb2a621565b0ca98e8b4228838c971e"}, - {file = "grimp-3.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:edeb78b27cee3e484e27d91accd585bfa399870cb1097f9132a8fdc920dcc584"}, - {file = "grimp-3.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:32993eaa86d3e65d302394c09228e17373720353640c7bc6847e40cac618db9e"}, - {file = "grimp-3.9-cp311-cp311-win32.whl", hash = "sha256:0e6cc81104b227a4185a2e2644f1ee70e90686174331c3d8004848ba9c811f08"}, - {file = "grimp-3.9-cp311-cp311-win_amd64.whl", hash = "sha256:088f5a67f67491a5d4c20ef67941cbbb15f928f78a412f0d032460ee2ce518fb"}, - {file = "grimp-3.9-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:c19a27aa7541b620df94ceafde89d6ebf9ee1b263e80d278ea45bdd504fec769"}, - {file = "grimp-3.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f68e7a771c9eb4459106decd6cc4f11313202b10d943a1a8bed463b528889dd0"}, - {file = "grimp-3.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8290eb4561dc29c590fc099f2bdac4827a9b86a018e146428854f9742ab480ef"}, - {file = "grimp-3.9-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4574c0d135e6af8cddc31ac9617c00aac3181bb4d476f5aea173a5f2ac8c7479"}, - {file = "grimp-3.9-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5e4110bd0aedd7da899e44ec0d4a93529e93f2d03e5786e3469a5f7562e11e9"}, - {file = "grimp-3.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d098f6e10c0e42c6be0eca2726a7d7218e90ba020141fa3f88426a5f7d09d71"}, - {file = "grimp-3.9-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69573ecc5cc84bb175e5aa5af2fe09dfb2f33a399c59c025f5f3d7d2f6f202fe"}, - {file = "grimp-3.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63e4bdb4382fb0afd52216e70a0e4da3f0500de8f9e40ee8d2b68a16a35c40c4"}, - {file = "grimp-3.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ddde011e9bb2fa1abb816373bd8898d1a486cf4f4b13dc46a11ddcd57406e1b"}, - {file = "grimp-3.9-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fa32eed6fb383ec4e54b4073e8ce75a5b151bb1f1d11be66be18aee04d3c9c4b"}, - {file = "grimp-3.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e9cc09977f8688839e0c9873fd214e11c971f5df38bffb31d402d04803dfff92"}, - {file = "grimp-3.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3a732b461db86403aa3c8154ffab85d1964c8c6adaa763803ce260abbc504b6f"}, - {file = "grimp-3.9-cp312-cp312-win32.whl", hash = "sha256:829d60b4c1c8c6bfb1c7348cf3e30b87f462a7d9316ced9d8265146a2153a0cd"}, - {file = "grimp-3.9-cp312-cp312-win_amd64.whl", hash = "sha256:556ab4fbf943299fd90e467d481803b8e1a57d28c24af5867012559f51435ceb"}, - {file = "grimp-3.9-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:867b476677b1d2f89b6c9ca0d7c47b279fe9d0230087f621c6aba94331411690"}, - {file = "grimp-3.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:faf5dd2cc7012a6024e743976674d55e66c6e556eaffd30e5843a88cc4623c16"}, - {file = "grimp-3.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ff6c0de2e9cffed8f7ec1a9c80888f01017806cfb9acf9c3d8fc3137a629d51"}, - {file = "grimp-3.9-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e38f92a650756f9b00198991cb60c5e3add9d68475425fb4fe0960d1586660ce"}, - {file = "grimp-3.9-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e1ef77c7841b15d9f5002c767da1060ec42cb477fa7ae33d7f9dffb4705dc0"}, - {file = "grimp-3.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:19a9bb0b05d1b0738920c604cdc544c9073df6edd71f31963054576647c8f897"}, - {file = "grimp-3.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9f9d5e6182859900610f15704847897115707b28ca2c9b5c754ef3bef9adb485"}, - {file = "grimp-3.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4e63efe9c2df2e8efe98142fa754ef9140e3aa3ce942ef55f52bb7a177a0822"}, - {file = "grimp-3.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e204b17675763a7091fd5e8b7c58c83c8383505d90b6aea6a5e0d5bb737cb856"}, - {file = "grimp-3.9-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:15d23a90d34d3f94e5437c7bc29ad1b82d059ed9b039c84d6ef20d83b826ca88"}, - {file = "grimp-3.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:04ed7f682ac07aee6e8cd99c1ea3d0ba26ea8167b71b4b79f05640982c1b1fa3"}, - {file = "grimp-3.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:75f33e7b98652ce17fc9a5d0dce0bc5f4ba68fd73a15f10dd4cd1ea511bab0c1"}, - {file = "grimp-3.9-cp313-cp313-win32.whl", hash = "sha256:72921d8727a508b34393a330748db91fca62fa506b86f5a4c457f713a6468c15"}, - {file = "grimp-3.9-cp313-cp313-win_amd64.whl", hash = "sha256:cd65bc6d030d9d788a1794e01cdc3b4abce2971cc821e2e7dc02d09c45febc56"}, - {file = "grimp-3.9-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:057d4f7e4b9f62909406701d5bab773b39e1fd8591043c6b19dba3ab3b275625"}, - {file = "grimp-3.9-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0c660f1222b7c11d725d298bce09b85376b0084d5515b8364a7a70c0547a0992"}, - {file = "grimp-3.9-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:78662f2c0ae4e7ff3eacff051e6b3110ed026135545a1825a53a858d4e966ebb"}, - {file = "grimp-3.9-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1b57b20f51ce7765adaffd80b3a17a365b770a5d237a772a2a8a74cc19c186f2"}, - {file = "grimp-3.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:335511ad698e2a7d6e15dccdb843afc6ad4bde79f213479c799f67c98ce36002"}, - {file = "grimp-3.9-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:574c94895d4fcac2e5ae794636fe687fb80b9ca59fe3bb8458d7a64bc3b3ed9e"}, - {file = "grimp-3.9-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:84c95f9df61ddaffd8f41a4181aa652f3fdf9932b26634cd8273d4dcd926321e"}, - {file = "grimp-3.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9ddcbfd11d6e6b813121db1116f6b3c4930ab433a949522b5e80542c5da3d805"}, - {file = "grimp-3.9-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5de1aedb52351f23f7a70cff66c16feacfd69567fb1cac04a9b0ea321760f2f5"}, - {file = "grimp-3.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:44e6785aed2dcce003900f41798c21ae8c6f5899f36e304870a86a75ade18a0d"}, - {file = "grimp-3.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbf998acdfa7ed87a70b0eba44cb240aec0273dc087f132c72ed1ad583625313"}, - {file = "grimp-3.9-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:751304b8de0525c1276299f72cd81df04367438cdb384ea7df98753f11e4342b"}, - {file = "grimp-3.9-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72675e36675479df1f933cff4969adb480037c0155461b6944d030bd83c46deb"}, - {file = "grimp-3.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a45d6042b9cabc4df9817745a531b746c0ead456550928219c7642ec05dd222"}, - {file = "grimp-3.9-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9a61fd84e01ce5d4ca150494c614cc4db2a6c974d454bca7f169dd03d52f741"}, - {file = "grimp-3.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c8bd22361a9cc5f602d9386ee271c260493dfab68a21c7f61ee5227c4407b7d"}, - {file = "grimp-3.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1d08a71a2d794f4c4fd891f96f6a37e8e83e562aa078f72eaaa3ca07ee8ab550"}, - {file = "grimp-3.9-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:f32902b833c9ef9208f2c62975ba234ab4204e7a6f79f919bde6dc2fc589531b"}, - {file = "grimp-3.9-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:11aafe1cbeb263a9a9f592feb957929bf7e7cef77a315ac3a13f9692eb8b16b1"}, - {file = "grimp-3.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bf316209ec7e2e46506e1ce3223b473f9869d01e88c6f01f78198434dd987bd5"}, - {file = "grimp-3.9-cp39-cp39-win32.whl", hash = "sha256:156d76ad1b2ac8967af0962909fda251e3f14a3ab2ee453a66ab12cf0186d3c4"}, - {file = "grimp-3.9-cp39-cp39-win_amd64.whl", hash = "sha256:6f66c9d037f4adeb30ea083da4e2a5d77411107ea86e488706864817e7663a76"}, - {file = "grimp-3.9-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c10a8dadb7094a4d437da37ad9c4782eb3d08c52b8e80aa9a9cfbf0d0d289203"}, - {file = "grimp-3.9-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9e86bc544056385041f9e5ff4f061fa88209219cee5689aa564d995ecb0bfe8"}, - {file = "grimp-3.9-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:94414e7c29117cc6bc92a68bc2fe81ad3c80469c410c6c7da14db10fb814b66c"}, - {file = "grimp-3.9-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c637b9f58e4a4a9265b3c1db5ff30d285495412b5baeeede676443c0bd9cb75b"}, - {file = "grimp-3.9-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e10be6c463ac6f519f5b9a047e57292f00162d750c61bbb19df8d0ef23144c71"}, - {file = "grimp-3.9-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6217f7bc2a2227bd0c7baaf2c84fee2e1fa504535838a58684675fcb1d05a144"}, - {file = "grimp-3.9-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2d6a2aa5e72a6b24b1df0904e0b73be3be037ac395a0f7c41c753cd1be21d0be"}, - {file = "grimp-3.9-pp310-pypy310_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:8e7dceec0c9651b3cbefe3bc59eaec6c74054d862630458db46e0be5bdbbbc85"}, - {file = "grimp-3.9-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:b6dbdb37c85d335e035db7670da118d12a9ea09662fe74a667706f6dda36d6dd"}, - {file = "grimp-3.9-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8125134fca3b89608efae89b82e2ab2156619492e26af6cb8d90e862d31b345e"}, - {file = "grimp-3.9-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61b9069230b38f50fe85adba1037a8c9abfb21d2e219ba7ee76e045b3ff2b119"}, - {file = "grimp-3.9-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c2bda4243558d3ddd349a135c3444ef20d6778471316bbe8e5ca84ffc7a97447"}, - {file = "grimp-3.9-pp311-pypy311_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9711f25ad6c03f33c14b158c4c83beaf906d544026a575f4aadd8dbd9d30594"}, - {file = "grimp-3.9-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:642139de62d81650fcf3130a68fc1a6db2e244a2c02d84ff98e6b73d70588de1"}, - {file = "grimp-3.9-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33b819a79171d8707583b40d3fc658f16758339da19496f0a49ae856cf904104"}, - {file = "grimp-3.9-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ff48e80a2c1ffde2c0b5b6e0a1f178058090f3d0e25b3ae1f2f00a9fb38a2fe"}, - {file = "grimp-3.9-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e087b54eb1b8b6d3171d986dbfdd9ad7d73df1944dfaa55d08d3c66b33c94638"}, - {file = "grimp-3.9-pp311-pypy311_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:a9c3bd888ea57dca279765078facba2d4ed460a2f19850190df6b1e5e498aef3"}, - {file = "grimp-3.9-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:5392b4f863dca505a6801af8be738228cdce5f1c71d90f7f8efba2cdc2f1a1cb"}, - {file = "grimp-3.9-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:7719cb213aacad7d0e6d69a9be4f998133d9b9ad3fa873b07dfaa221131ac2dc"}, - {file = "grimp-3.9-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39e0fdc42b55954e26c595e7c9ac477218d4a342024b198d90ab76ec82263065"}, - {file = "grimp-3.9-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99eb44ecb368c0f224247697298182db1858b1142e612a13f6e251acbe27d2ac"}, - {file = "grimp-3.9-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0e4c3766190e1e21d80f368e4a8c48d306fd4ba568ad6168947d39b2d1edd029"}, - {file = "grimp-3.9-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8cb92110ded311474b90f30acef51fd23b458c89252ce5a41a1933f39ad8abf7"}, - {file = "grimp-3.9-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:badfc77336e950d3c40ff1338fe32bf603c0afebd7582cbfb34905eb4f85fca1"}, - {file = "grimp-3.9-pp39-pypy39_pp73-musllinux_1_2_armv7l.whl", hash = "sha256:1ddd50c4f62196adcb14999ec49381a41f8404ea166e4d25afb8f944ebaa1728"}, - {file = "grimp-3.9-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:b994de7d526825bbfc51d1bf1e4ce6037acf0b6a264422029d02adb591575e28"}, - {file = "grimp-3.9-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:434b53437fd06071e94db6c2979b686e14d5995dc7c2ca3fe0793ef489c427da"}, - {file = "grimp-3.9.tar.gz", hash = "sha256:b677ac17301d7e0f1e19cc7057731bd7956a2121181eb5057e51efb44301fb0a"}, -] - -[package.dependencies] -joblib = ">=1.3.0" -typing-extensions = ">=3.10.0.0" - -[[package]] -name = "idna" -version = "3.10" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "import-linter" -version = "2.3" -description = "Enforces rules for the imports within and between Python packages." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "import_linter-2.3-py3-none-any.whl", hash = "sha256:5b851776782048ff1be214f1e407ef2e3d30dcb23194e8b852772941811a1258"}, - {file = "import_linter-2.3.tar.gz", hash = "sha256:863646106d52ee5489965670f97a2a78f2c8c68d2d20392322bf0d7cc0111aa7"}, -] - -[package.dependencies] -click = ">=6" -grimp = ">=3.7" -typing-extensions = ">=3.10.0.0" - -[[package]] -name = "iniconfig" -version = "2.1.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, - {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, -] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -groups = ["dev"] -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "joblib" -version = "1.5.0" -description = "Lightweight pipelining with Python functions" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "joblib-1.5.0-py3-none-any.whl", hash = "sha256:206144b320246485b712fc8cc51f017de58225fa8b414a1fe1764a7231aca491"}, - {file = "joblib-1.5.0.tar.gz", hash = "sha256:d8757f955389a3dd7a23152e43bc297c2e0c2d3060056dad0feefc88a06939b5"}, -] - -[[package]] -name = "loguru" -version = "0.7.3" -description = "Python logging made (stupidly) simple" -optional = false -python-versions = "<4.0,>=3.5" -groups = ["main"] -files = [ - {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, - {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==v0.910) ; python_version < \"3.6\"", "mypy (==v0.971) ; python_version == \"3.6\"", "mypy (==v1.13.0) ; python_version >= \"3.8\"", "mypy (==v1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] - -[[package]] -name = "lsprotocol" -version = "2024.0.0b1" -description = "Python types for Language Server Protocol." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "lsprotocol-2024.0.0b1-py3-none-any.whl", hash = "sha256:93785050ac155ae2be16b1ebfbd74c214feb3d3ef77b10399ce941e5ccef6ebd"}, - {file = "lsprotocol-2024.0.0b1.tar.gz", hash = "sha256:d3667fb70894d361aa6c495c5c8a1b2e6a44be65ff84c21a9cbb67ebfb4830fd"}, -] - -[package.dependencies] -attrs = ">=21.3.0" -cattrs = "!=23.2.1" - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mypy" -version = "1.15.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, - {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, - {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, - {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, - {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, - {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, - {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, - {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, - {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, - {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, - {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, - {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, - {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, - {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "ordered-set" -version = "4.1.0" -description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, - {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"}, -] - -[package.extras] -dev = ["black", "mypy", "pytest"] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.3.8" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -files = [ - {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, - {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] - -[[package]] -name = "pluggy" -version = "1.6.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, - {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["coverage", "pytest", "pytest-benchmark"] - -[[package]] -name = "pycodestyle" -version = "2.13.0" -description = "Python style guide checker" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9"}, - {file = "pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae"}, -] - -[[package]] -name = "pydantic" -version = "2.10.6" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, - {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.27.2" -typing-extensions = ">=4.12.2" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.27.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, - {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pyflakes" -version = "3.3.2" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a"}, - {file = "pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b"}, -] - -[[package]] -name = "pygls" -version = "2.0.0a2" -description = "A pythonic generic language server (pronounced like 'pie glass')" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pygls-2.0.0a2-py3-none-any.whl", hash = "sha256:b202369321409343aa6440d73111d9fa0c22e580466ff1c7696b8358bb91f243"}, - {file = "pygls-2.0.0a2.tar.gz", hash = "sha256:03e00634ed8d989918268aaa4b4a0c3ab857ea2d4ee94514a52efa5ddd6d5d9f"}, -] - -[package.dependencies] -cattrs = ">=23.1.2" -lsprotocol = "2024.0.0b1" - -[package.extras] -ws = ["websockets (>=13.0)"] - -[[package]] -name = "pytest" -version = "7.4.4" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, - {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=0.12,<2.0" - -[package.extras] -testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "tomlkit" -version = "0.11.8" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, - {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, -] - -[[package]] -name = "types-flake8" -version = "7.2.0.20250330" -description = "Typing stubs for flake8" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "types_flake8-7.2.0.20250330-py3-none-any.whl", hash = "sha256:af31590a269586309b80a439c94e59359e139e17475a8fc8d3c426ab01a40547"}, - {file = "types_flake8-7.2.0.20250330.tar.gz", hash = "sha256:481e5c914a26fabd23e85704ad055f2716f9238740bfe6fe77259c2533cb970c"}, -] - -[package.dependencies] -types-pyflakes = "*" - -[[package]] -name = "types-pyflakes" -version = "3.3.2.20250511" -description = "Typing stubs for pyflakes" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "types_pyflakes-3.3.2.20250511-py3-none-any.whl", hash = "sha256:85802fdd0b64d3553ef12ac0ba02d85c4bbd38747579c544e6bb005ec455becf"}, - {file = "types_pyflakes-3.3.2.20250511.tar.gz", hash = "sha256:d0ef58f9ec15eab2a9e427814f48587be4eb2752a8ae7dec201d65086f50ace2"}, -] - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "watchdog" -version = "4.0.2" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8"}, - {file = "watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19"}, - {file = "watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b"}, - {file = "watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c"}, - {file = "watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[[package]] -name = "win32-setctime" -version = "1.2.0" -description = "A small Python utility to set file creation time on Windows" -optional = false -python-versions = ">=3.5" -groups = ["main"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, - {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, -] - -[package.extras] -dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] - -[metadata] -lock-version = "2.1" -python-versions = ">=3.11, < 3.14" -content-hash = "3f14e2690a4711f544fa35cd2f9433c3c571df472fc8f4fd39c7b84020399470" diff --git a/poetry.toml b/poetry.toml deleted file mode 100644 index d11b90b..0000000 --- a/poetry.toml +++ /dev/null @@ -1,2 +0,0 @@ -[virtualenvs] -prefer-active-python = true diff --git a/presets/fine_python_format/fine_python_format/preset.toml b/presets/fine_python_format/fine_python_format/preset.toml index 06451ed..9a660cb 100644 --- a/presets/fine_python_format/fine_python_format/preset.toml +++ b/presets/fine_python_format/fine_python_format/preset.toml @@ -1,12 +1,19 @@ [tool.finecode.action.format] source = "finecode_extension_api.actions.format.FormatAction" handlers = [ - { name = "isort", source = "fine_python_isort.IsortFormatHandler" }, - { name = "black", source = "fine_python_black.BlackFormatHandler" }, - { name = "save", source = "finecode_extension_api.actions.format.SaveFormatHandler" }, + { name = "isort", source = "fine_python_isort.IsortFormatHandler", env = "dev_no_runtime", dependencies = [ + "fine_python_black==0.2.*", + ] }, + { name = "black", source = "fine_python_black.BlackFormatHandler", env = "dev_no_runtime", dependencies = [ + "fine_python_isort==0.2.*", + ] }, + { name = "save", source = "finecode_extension_api.actions.format.SaveFormatHandler", env = "dev_no_runtime", dependencies = [ + "finecode_extension_api==0.3.*", + ] }, ] -[tool.finecode.action_handler.isort.config] +[[tool.finecode.action_handler]] +source = "fine_python_isort.IsortFormatHandler" # make isort config compatible with black # see https://black.readthedocs.io/en/stable/guides/using_black_with_other_tools.html#isort -profile = "black" +config.profile = "black" diff --git a/presets/fine_python_format/poetry.lock b/presets/fine_python_format/poetry.lock deleted file mode 100644 index 0551df1..0000000 --- a/presets/fine_python_format/poetry.lock +++ /dev/null @@ -1,888 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "attrs" -version = "25.3.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, - {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, -] - -[package.extras] -benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] - -[[package]] -name = "black" -version = "25.1.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, - {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, - {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, - {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, - {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, - {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, - {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, - {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, - {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, - {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, - {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, - {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, - {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, - {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, - {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, - {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, - {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, - {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, - {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, - {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, - {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, - {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "cattrs" -version = "24.1.3" -description = "Composable complex class support for attrs and dataclasses." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "cattrs-24.1.3-py3-none-any.whl", hash = "sha256:adf957dddd26840f27ffbd060a6c4dd3b2192c5b7c2c0525ef1bd8131d8a83f5"}, - {file = "cattrs-24.1.3.tar.gz", hash = "sha256:981a6ef05875b5bb0c7fb68885546186d306f10f0f6718fe9b96c226e68821ff"}, -] - -[package.dependencies] -attrs = ">=23.1.0" - -[package.extras] -bson = ["pymongo (>=4.4.0)"] -cbor2 = ["cbor2 (>=5.4.6)"] -msgpack = ["msgpack (>=1.0.5)"] -msgspec = ["msgspec (>=0.18.5) ; implementation_name == \"cpython\""] -orjson = ["orjson (>=3.9.2) ; implementation_name == \"cpython\""] -pyyaml = ["pyyaml (>=6.0)"] -tomlkit = ["tomlkit (>=0.11.8)"] -ujson = ["ujson (>=5.7.0)"] - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -markers = {main = "platform_system == \"Windows\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\""} - -[[package]] -name = "fine-python-aksem" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_module_exports = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_module_exports"} - -[package.source] -type = "git" -url = "https://github.com/Aksem/fine_python_aksem.git" -reference = "HEAD" -resolved_reference = "56ce22c3fb1228a6e85d1a8727a0fa74787608d9" - -[[package]] -name = "fine-python-ast" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = "0.1.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "f0b0757ea2a6dcd5ce8db13bba72dd04d404fa5b" -subdirectory = "extensions/fine_python_ast" - -[[package]] -name = "fine-python-black" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_black-0.1.0-py3-none-any.whl", hash = "sha256:27a012123783e4217222546e37280660e5a4948cdd3aa12d7fae7a3ce21a875d"}, - {file = "fine_python_black-0.1.0.tar.gz", hash = "sha256:ce300e897b4d819abe4754177cd5b81d29b2d4d04233942135edc1a8ed234bf7"}, -] - -[package.dependencies] -black = ">=25.1.0,<26.0.0" -finecode_extension_api = "0.1.0" - -[[package]] -name = "fine-python-flake8" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_ast = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_ast"} -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} -flake8 = ">=7.1.2,<8.0.0" -types-flake8 = ">=7.1.0.20241020,<8.0.0.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "f0b0757ea2a6dcd5ce8db13bba72dd04d404fa5b" -subdirectory = "extensions/fine_python_flake8" - -[[package]] -name = "fine-python-isort" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_isort-0.1.0-py3-none-any.whl", hash = "sha256:cbd6cd5502d65122e9f6461758f78db8d9e5628ab97c41a67ee6ef85a3526c8e"}, - {file = "fine_python_isort-0.1.0.tar.gz", hash = "sha256:64468a96b49663226b422885b25de7c22c24f6dafef6c25c1d02ea6e49662b53"}, -] - -[package.dependencies] -finecode_extension_api = "0.1.0" -isort = ">=5.13,<6" - -[[package]] -name = "fine-python-lint" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_flake8 = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_flake8"} -fine_python_mypy = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_mypy"} -flake8-bugbear = ">=24.12.12,<25.0.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "f0b0757ea2a6dcd5ce8db13bba72dd04d404fa5b" -subdirectory = "presets/fine_python_lint" - -[[package]] -name = "fine-python-module-exports" -version = "0.1.0" -description = "" -optional = false -python-versions = ">= 3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_ast = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_ast"} -finecode_extension_api = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "finecode_extension_api"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "f0b0757ea2a6dcd5ce8db13bba72dd04d404fa5b" -subdirectory = "extensions/fine_python_module_exports" - -[[package]] -name = "fine-python-mypy" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -finecode_extension_api = "0.1.0" -mypy = ">=1.15,<2.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "f0b0757ea2a6dcd5ce8db13bba72dd04d404fa5b" -subdirectory = "extensions/fine_python_mypy" - -[[package]] -name = "fine-python-recommended" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_format = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_format"} -fine_python_lint = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_lint"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "f0b0757ea2a6dcd5ce8db13bba72dd04d404fa5b" -subdirectory = "presets/fine_python_recommended" - -[[package]] -name = "finecode" -version = "0.2.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["dev"] -files = [ - {file = "finecode-0.2.0-py3-none-any.whl", hash = "sha256:42e4980a219a91e9c8a84e51d5df3f7c43d160230bb0fb6001a3e4f28a42041c"}, - {file = "finecode-0.2.0.tar.gz", hash = "sha256:149001825d27403e18c935f67b710184cea3cf3b846283996a595fabcc41d67e"}, -] - -[package.dependencies] -click = "==8.1.*" -finecode_extension_api = "0.1.0" -loguru = "==0.7.*" -ordered-set = "==4.1.*" -platformdirs = "==4.3.*" -pydantic = "==2.10.*" -pygls = "2.0.0-a2" -tomlkit = "==0.11.*" -watchdog = "==4.0.*" - -[[package]] -name = "finecode-dev-common-preset" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = true - -[package.dependencies] -fine_python_aksem = {git = "https://github.com/Aksem/fine_python_aksem.git"} -fine_python_recommended = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_recommended"} - -[package.source] -type = "directory" -url = "../../finecode_dev_common_preset" - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["main", "dev"] -files = [] -develop = false - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "f0b0757ea2a6dcd5ce8db13bba72dd04d404fa5b" -subdirectory = "finecode_extension_api" - -[[package]] -name = "flake8" -version = "7.2.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343"}, - {file = "flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.13.0,<2.14.0" -pyflakes = ">=3.3.0,<3.4.0" - -[[package]] -name = "flake8-bugbear" -version = "24.12.12" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -optional = false -python-versions = ">=3.8.1" -groups = ["dev"] -files = [ - {file = "flake8_bugbear-24.12.12-py3-none-any.whl", hash = "sha256:1b6967436f65ca22a42e5373aaa6f2d87966ade9aa38d4baf2a1be550767545e"}, - {file = "flake8_bugbear-24.12.12.tar.gz", hash = "sha256:46273cef0a6b6ff48ca2d69e472f41420a42a46e24b2a8972e4f0d6733d12a64"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -flake8 = ">=6.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "loguru" -version = "0.7.3" -description = "Python logging made (stupidly) simple" -optional = false -python-versions = "<4.0,>=3.5" -groups = ["dev"] -files = [ - {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, - {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==v0.910) ; python_version < \"3.6\"", "mypy (==v0.971) ; python_version == \"3.6\"", "mypy (==v1.13.0) ; python_version >= \"3.8\"", "mypy (==v1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] - -[[package]] -name = "lsprotocol" -version = "2024.0.0b1" -description = "Python types for Language Server Protocol." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "lsprotocol-2024.0.0b1-py3-none-any.whl", hash = "sha256:93785050ac155ae2be16b1ebfbd74c214feb3d3ef77b10399ce941e5ccef6ebd"}, - {file = "lsprotocol-2024.0.0b1.tar.gz", hash = "sha256:d3667fb70894d361aa6c495c5c8a1b2e6a44be65ff84c21a9cbb67ebfb4830fd"}, -] - -[package.dependencies] -attrs = ">=21.3.0" -cattrs = "!=23.2.1" - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -groups = ["dev"] -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mypy" -version = "1.15.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, - {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, - {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, - {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, - {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, - {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, - {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, - {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, - {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, - {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, - {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, - {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, - {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, - {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "ordered-set" -version = "4.1.0" -description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, - {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"}, -] - -[package.extras] -dev = ["black", "mypy", "pytest"] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.3.8" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -files = [ - {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, - {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] - -[[package]] -name = "pycodestyle" -version = "2.13.0" -description = "Python style guide checker" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9"}, - {file = "pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae"}, -] - -[[package]] -name = "pydantic" -version = "2.10.6" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, - {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.27.2" -typing-extensions = ">=4.12.2" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.27.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, - {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pyflakes" -version = "3.3.2" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a"}, - {file = "pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b"}, -] - -[[package]] -name = "pygls" -version = "2.0.0a2" -description = "A pythonic generic language server (pronounced like 'pie glass')" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pygls-2.0.0a2-py3-none-any.whl", hash = "sha256:b202369321409343aa6440d73111d9fa0c22e580466ff1c7696b8358bb91f243"}, - {file = "pygls-2.0.0a2.tar.gz", hash = "sha256:03e00634ed8d989918268aaa4b4a0c3ab857ea2d4ee94514a52efa5ddd6d5d9f"}, -] - -[package.dependencies] -cattrs = ">=23.1.2" -lsprotocol = "2024.0.0b1" - -[package.extras] -ws = ["websockets (>=13.0)"] - -[[package]] -name = "tomlkit" -version = "0.11.8" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, - {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, -] - -[[package]] -name = "types-flake8" -version = "7.2.0.20250330" -description = "Typing stubs for flake8" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "types_flake8-7.2.0.20250330-py3-none-any.whl", hash = "sha256:af31590a269586309b80a439c94e59359e139e17475a8fc8d3c426ab01a40547"}, - {file = "types_flake8-7.2.0.20250330.tar.gz", hash = "sha256:481e5c914a26fabd23e85704ad055f2716f9238740bfe6fe77259c2533cb970c"}, -] - -[package.dependencies] -types-pyflakes = "*" - -[[package]] -name = "types-pyflakes" -version = "3.3.2.20250511" -description = "Typing stubs for pyflakes" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "types_pyflakes-3.3.2.20250511-py3-none-any.whl", hash = "sha256:85802fdd0b64d3553ef12ac0ba02d85c4bbd38747579c544e6bb005ec455becf"}, - {file = "types_pyflakes-3.3.2.20250511.tar.gz", hash = "sha256:d0ef58f9ec15eab2a9e427814f48587be4eb2752a8ae7dec201d65086f50ace2"}, -] - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "watchdog" -version = "4.0.2" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8"}, - {file = "watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19"}, - {file = "watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b"}, - {file = "watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c"}, - {file = "watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[[package]] -name = "win32-setctime" -version = "1.2.0" -description = "A small Python utility to set file creation time on Windows" -optional = false -python-versions = ">=3.5" -groups = ["dev"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, - {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, -] - -[package.extras] -dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] - -[metadata] -lock-version = "2.1" -python-versions = ">=3.11, < 3.14" -content-hash = "ac458ef2e905b22924e27f83a2877219858789d6310947e73636a6a13007603a" diff --git a/presets/fine_python_format/pyproject.toml b/presets/fine_python_format/pyproject.toml index 5173275..5d99042 100644 --- a/presets/fine_python_format/pyproject.toml +++ b/presets/fine_python_format/pyproject.toml @@ -1,16 +1,15 @@ [project] name = "fine-python-format" -version = "0.1.0" +version = "0.2.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">=3.11, < 3.14" -dependencies = ["fine_python_black==0.1.0", "fine_python_isort==0.1.0"] - -[tool.poetry.group.dev.dependencies] -finecode = { version = "0.2.0" } -finecode_dev_common_preset = { path = "../../finecode_dev_common_preset", develop = true } +dependencies = ["finecode_extension_api==0.3.*"] [build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +requires = ["setuptools>=64"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.package-data] +fine_python_format = ["preset.toml"] diff --git a/presets/fine_python_format/setup.py b/presets/fine_python_format/setup.py new file mode 100644 index 0000000..435d2a1 --- /dev/null +++ b/presets/fine_python_format/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_format", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/presets/fine_python_lint/fine_python_lint/preset.toml b/presets/fine_python_lint/fine_python_lint/preset.toml index eae1276..0c97b72 100644 --- a/presets/fine_python_lint/fine_python_lint/preset.toml +++ b/presets/fine_python_lint/fine_python_lint/preset.toml @@ -1,13 +1,19 @@ [tool.finecode.action.lint] source = "finecode_extension_api.actions.lint.LintAction" handlers = [ - { name = "flake8", source = "fine_python_flake8.Flake8LintHandler" }, - { name = "mypy", source = "fine_python_mypy.MypyLintHandler" }, + { name = "flake8", source = "fine_python_flake8.Flake8LintHandler", env = "dev_no_runtime", dependencies = [ + "fine_python_flake8==0.2.*", + "flake8-bugbear (>=24.12.12,<25.0.0)", + ] }, + { name = "mypy", source = "fine_python_mypy.MypyLintHandler", env = "dev_no_runtime", dependencies = [ + "fine_python_mypy==0.2.*", + ] }, ] -[tool.finecode.action_handler.flake8.config] -max_line_length = 80 -extend_select = ["B950"] +[[tool.finecode.action_handler]] +source = "fine_python_flake8.Flake8LintHandler" +config.max_line_length = 80 +config.extend_select = ["B950"] # W391 is not compatible with black, because black adds an empty line to the end of the file # TODO: move in recommended config once config merging is implemented -extend_ignore = ["E203", "E501", "E701", "W391"] +config.extend_ignore = ["E203", "E501", "E701", "W391"] diff --git a/presets/fine_python_lint/poetry.lock b/presets/fine_python_lint/poetry.lock deleted file mode 100644 index 8470d13..0000000 --- a/presets/fine_python_lint/poetry.lock +++ /dev/null @@ -1,867 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "attrs" -version = "25.3.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, - {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, -] - -[package.extras] -benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] - -[[package]] -name = "black" -version = "25.1.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, - {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, - {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, - {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, - {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, - {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, - {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, - {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, - {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, - {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, - {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, - {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, - {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, - {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, - {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, - {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, - {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, - {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, - {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, - {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, - {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, - {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "cattrs" -version = "24.1.3" -description = "Composable complex class support for attrs and dataclasses." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "cattrs-24.1.3-py3-none-any.whl", hash = "sha256:adf957dddd26840f27ffbd060a6c4dd3b2192c5b7c2c0525ef1bd8131d8a83f5"}, - {file = "cattrs-24.1.3.tar.gz", hash = "sha256:981a6ef05875b5bb0c7fb68885546186d306f10f0f6718fe9b96c226e68821ff"}, -] - -[package.dependencies] -attrs = ">=23.1.0" - -[package.extras] -bson = ["pymongo (>=4.4.0)"] -cbor2 = ["cbor2 (>=5.4.6)"] -msgpack = ["msgpack (>=1.0.5)"] -msgspec = ["msgspec (>=0.18.5) ; implementation_name == \"cpython\""] -orjson = ["orjson (>=3.9.2) ; implementation_name == \"cpython\""] -pyyaml = ["pyyaml (>=6.0)"] -tomlkit = ["tomlkit (>=0.11.8)"] -ujson = ["ujson (>=5.7.0)"] - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["dev"] -markers = "sys_platform == \"win32\" or platform_system == \"Windows\"" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "fine-python-aksem" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_module_exports = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_module_exports"} - -[package.source] -type = "git" -url = "https://github.com/Aksem/fine_python_aksem.git" -reference = "HEAD" -resolved_reference = "56ce22c3fb1228a6e85d1a8727a0fa74787608d9" - -[[package]] -name = "fine-python-ast" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main", "dev"] -files = [ - {file = "fine_python_ast-0.1.0-py3-none-any.whl", hash = "sha256:3dcdcdc40ed89e0b90686f2ad5d358d8edba622a5de4c1f52f2f0787dcc4e07d"}, - {file = "fine_python_ast-0.1.0.tar.gz", hash = "sha256:ebc68aef7d0379f8771f610e436f6075b7c299a8895f1b9b7769fd038f95397e"}, -] - -[package.dependencies] -finecode_extension_api = "0.1.0" - -[[package]] -name = "fine-python-black" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["dev"] -files = [ - {file = "fine_python_black-0.1.0-py3-none-any.whl", hash = "sha256:27a012123783e4217222546e37280660e5a4948cdd3aa12d7fae7a3ce21a875d"}, - {file = "fine_python_black-0.1.0.tar.gz", hash = "sha256:ce300e897b4d819abe4754177cd5b81d29b2d4d04233942135edc1a8ed234bf7"}, -] - -[package.dependencies] -black = ">=25.1.0,<26.0.0" -finecode_extension_api = "0.1.0" - -[[package]] -name = "fine-python-flake8" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_flake8-0.1.0-py3-none-any.whl", hash = "sha256:7ed7641505936f334396631f779953a13ae18c8f207a8258d722e50fa452d792"}, - {file = "fine_python_flake8-0.1.0.tar.gz", hash = "sha256:ccba9a1ec41f5f3aa756efa63bd64650237ad63d3098aedf673e9c254e502914"}, -] - -[package.dependencies] -fine_python_ast = "0.1.0" -finecode_extension_api = "0.1.0" -flake8 = ">=7.1.2,<8.0.0" -types-flake8 = ">=7.1.0.20241020,<8.0.0.0" - -[[package]] -name = "fine-python-format" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_black = "0.1.0" -fine_python_isort = "0.1.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "959289157b4a3fe7bc21387a3c079c16e9c2a65e" -subdirectory = "presets/fine_python_format" - -[[package]] -name = "fine-python-isort" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["dev"] -files = [ - {file = "fine_python_isort-0.1.0-py3-none-any.whl", hash = "sha256:cbd6cd5502d65122e9f6461758f78db8d9e5628ab97c41a67ee6ef85a3526c8e"}, - {file = "fine_python_isort-0.1.0.tar.gz", hash = "sha256:64468a96b49663226b422885b25de7c22c24f6dafef6c25c1d02ea6e49662b53"}, -] - -[package.dependencies] -finecode_extension_api = "0.1.0" -isort = ">=5.13,<6" - -[[package]] -name = "fine-python-module-exports" -version = "0.1.0" -description = "" -optional = false -python-versions = ">= 3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_ast = "0.1.0" -finecode_extension_api = "0.1.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "959289157b4a3fe7bc21387a3c079c16e9c2a65e" -subdirectory = "extensions/fine_python_module_exports" - -[[package]] -name = "fine-python-mypy" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_mypy-0.1.0-py3-none-any.whl", hash = "sha256:cf1df00ad835fb85aa26480210a08ff963ffa560db123a62adea4a10a3684563"}, - {file = "fine_python_mypy-0.1.0.tar.gz", hash = "sha256:ece18604bdff098c3fd154cd138af74d82276fec20a1ae7ad03114427688e6f6"}, -] - -[package.dependencies] -finecode_extension_api = "0.1.0" -mypy = ">=1.15,<2.0" - -[[package]] -name = "fine-python-recommended" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_format = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_format"} -fine_python_lint = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_lint"} - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "959289157b4a3fe7bc21387a3c079c16e9c2a65e" -subdirectory = "presets/fine_python_recommended" - -[[package]] -name = "finecode" -version = "0.2.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["dev"] -files = [ - {file = "finecode-0.2.0-py3-none-any.whl", hash = "sha256:42e4980a219a91e9c8a84e51d5df3f7c43d160230bb0fb6001a3e4f28a42041c"}, - {file = "finecode-0.2.0.tar.gz", hash = "sha256:149001825d27403e18c935f67b710184cea3cf3b846283996a595fabcc41d67e"}, -] - -[package.dependencies] -click = "==8.1.*" -finecode_extension_api = "0.1.0" -loguru = "==0.7.*" -ordered-set = "==4.1.*" -platformdirs = "==4.3.*" -pydantic = "==2.10.*" -pygls = "2.0.0-a2" -tomlkit = "==0.11.*" -watchdog = "==4.0.*" - -[[package]] -name = "finecode-dev-common-preset" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = true - -[package.dependencies] -fine_python_aksem = {git = "https://github.com/Aksem/fine_python_aksem.git"} -fine_python_recommended = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_recommended"} - -[package.source] -type = "directory" -url = "../../finecode_dev_common_preset" - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main", "dev"] -files = [ - {file = "finecode_extension_api-0.1.0-py3-none-any.whl", hash = "sha256:55d4448a1a2f7224c3fdf05879fa9782246c0a85dc1dfb17543374fd808c2b5b"}, - {file = "finecode_extension_api-0.1.0.tar.gz", hash = "sha256:dee16c180e4cd318f71bf7a94b6ae425667153f8fb62630ab60db9b034f45595"}, -] - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[[package]] -name = "flake8" -version = "7.2.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343"}, - {file = "flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.13.0,<2.14.0" -pyflakes = ">=3.3.0,<3.4.0" - -[[package]] -name = "flake8-bugbear" -version = "24.12.12" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -optional = false -python-versions = ">=3.8.1" -groups = ["main"] -files = [ - {file = "flake8_bugbear-24.12.12-py3-none-any.whl", hash = "sha256:1b6967436f65ca22a42e5373aaa6f2d87966ade9aa38d4baf2a1be550767545e"}, - {file = "flake8_bugbear-24.12.12.tar.gz", hash = "sha256:46273cef0a6b6ff48ca2d69e472f41420a42a46e24b2a8972e4f0d6733d12a64"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -flake8 = ">=6.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -groups = ["dev"] -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "loguru" -version = "0.7.3" -description = "Python logging made (stupidly) simple" -optional = false -python-versions = "<4.0,>=3.5" -groups = ["dev"] -files = [ - {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, - {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==v0.910) ; python_version < \"3.6\"", "mypy (==v0.971) ; python_version == \"3.6\"", "mypy (==v1.13.0) ; python_version >= \"3.8\"", "mypy (==v1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] - -[[package]] -name = "lsprotocol" -version = "2024.0.0b1" -description = "Python types for Language Server Protocol." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "lsprotocol-2024.0.0b1-py3-none-any.whl", hash = "sha256:93785050ac155ae2be16b1ebfbd74c214feb3d3ef77b10399ce941e5ccef6ebd"}, - {file = "lsprotocol-2024.0.0b1.tar.gz", hash = "sha256:d3667fb70894d361aa6c495c5c8a1b2e6a44be65ff84c21a9cbb67ebfb4830fd"}, -] - -[package.dependencies] -attrs = ">=21.3.0" -cattrs = "!=23.2.1" - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mypy" -version = "1.15.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, - {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, - {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, - {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, - {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, - {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, - {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, - {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, - {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, - {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, - {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, - {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, - {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, - {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "ordered-set" -version = "4.1.0" -description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, - {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"}, -] - -[package.extras] -dev = ["black", "mypy", "pytest"] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.3.8" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, - {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] - -[[package]] -name = "pycodestyle" -version = "2.13.0" -description = "Python style guide checker" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9"}, - {file = "pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae"}, -] - -[[package]] -name = "pydantic" -version = "2.10.6" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, - {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.27.2" -typing-extensions = ">=4.12.2" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.27.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, - {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pyflakes" -version = "3.3.2" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a"}, - {file = "pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b"}, -] - -[[package]] -name = "pygls" -version = "2.0.0a2" -description = "A pythonic generic language server (pronounced like 'pie glass')" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pygls-2.0.0a2-py3-none-any.whl", hash = "sha256:b202369321409343aa6440d73111d9fa0c22e580466ff1c7696b8358bb91f243"}, - {file = "pygls-2.0.0a2.tar.gz", hash = "sha256:03e00634ed8d989918268aaa4b4a0c3ab857ea2d4ee94514a52efa5ddd6d5d9f"}, -] - -[package.dependencies] -cattrs = ">=23.1.2" -lsprotocol = "2024.0.0b1" - -[package.extras] -ws = ["websockets (>=13.0)"] - -[[package]] -name = "tomlkit" -version = "0.11.8" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, - {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, -] - -[[package]] -name = "types-flake8" -version = "7.2.0.20250330" -description = "Typing stubs for flake8" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "types_flake8-7.2.0.20250330-py3-none-any.whl", hash = "sha256:af31590a269586309b80a439c94e59359e139e17475a8fc8d3c426ab01a40547"}, - {file = "types_flake8-7.2.0.20250330.tar.gz", hash = "sha256:481e5c914a26fabd23e85704ad055f2716f9238740bfe6fe77259c2533cb970c"}, -] - -[package.dependencies] -types-pyflakes = "*" - -[[package]] -name = "types-pyflakes" -version = "3.3.2.20250511" -description = "Typing stubs for pyflakes" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "types_pyflakes-3.3.2.20250511-py3-none-any.whl", hash = "sha256:85802fdd0b64d3553ef12ac0ba02d85c4bbd38747579c544e6bb005ec455becf"}, - {file = "types_pyflakes-3.3.2.20250511.tar.gz", hash = "sha256:d0ef58f9ec15eab2a9e427814f48587be4eb2752a8ae7dec201d65086f50ace2"}, -] - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "watchdog" -version = "4.0.2" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8"}, - {file = "watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19"}, - {file = "watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b"}, - {file = "watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c"}, - {file = "watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[[package]] -name = "win32-setctime" -version = "1.2.0" -description = "A small Python utility to set file creation time on Windows" -optional = false -python-versions = ">=3.5" -groups = ["dev"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, - {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, -] - -[package.extras] -dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] - -[metadata] -lock-version = "2.1" -python-versions = ">=3.11, < 3.14" -content-hash = "503c582ffe07c09630f15e21394a4d290cf2485eb7604eb52716b1bc681132c8" diff --git a/presets/fine_python_lint/pyproject.toml b/presets/fine_python_lint/pyproject.toml index 4cd9e54..ead7668 100644 --- a/presets/fine_python_lint/pyproject.toml +++ b/presets/fine_python_lint/pyproject.toml @@ -1,20 +1,15 @@ [project] name = "fine-python-lint" -version = "0.1.0" +version = "0.2.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">=3.11, < 3.14" -dependencies = [ - "fine_python_mypy==0.1.0", - "fine_python_flake8==0.1.0", - "flake8-bugbear (>=24.12.12,<25.0.0)", -] - -[tool.poetry.group.dev.dependencies] -finecode = { version = "0.2.0" } -finecode_dev_common_preset = { path = "../../finecode_dev_common_preset", develop = true } +dependencies = ["finecode_extension_api==0.3.*"] [build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +requires = ["setuptools>=64"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.package-data] +fine_python_lint = ["preset.toml"] diff --git a/presets/fine_python_lint/setup.py b/presets/fine_python_lint/setup.py new file mode 100644 index 0000000..3779603 --- /dev/null +++ b/presets/fine_python_lint/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_lint", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/presets/fine_python_recommended/poetry.lock b/presets/fine_python_recommended/poetry.lock deleted file mode 100644 index ffcd3a4..0000000 --- a/presets/fine_python_recommended/poetry.lock +++ /dev/null @@ -1,858 +0,0 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "attrs" -version = "25.3.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, - {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, -] - -[package.extras] -benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] -tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] - -[[package]] -name = "black" -version = "25.1.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32"}, - {file = "black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da"}, - {file = "black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7"}, - {file = "black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9"}, - {file = "black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0"}, - {file = "black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299"}, - {file = "black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096"}, - {file = "black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2"}, - {file = "black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b"}, - {file = "black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc"}, - {file = "black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f"}, - {file = "black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba"}, - {file = "black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f"}, - {file = "black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3"}, - {file = "black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171"}, - {file = "black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18"}, - {file = "black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0"}, - {file = "black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f"}, - {file = "black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e"}, - {file = "black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355"}, - {file = "black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717"}, - {file = "black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "cattrs" -version = "24.1.3" -description = "Composable complex class support for attrs and dataclasses." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "cattrs-24.1.3-py3-none-any.whl", hash = "sha256:adf957dddd26840f27ffbd060a6c4dd3b2192c5b7c2c0525ef1bd8131d8a83f5"}, - {file = "cattrs-24.1.3.tar.gz", hash = "sha256:981a6ef05875b5bb0c7fb68885546186d306f10f0f6718fe9b96c226e68821ff"}, -] - -[package.dependencies] -attrs = ">=23.1.0" - -[package.extras] -bson = ["pymongo (>=4.4.0)"] -cbor2 = ["cbor2 (>=5.4.6)"] -msgpack = ["msgpack (>=1.0.5)"] -msgspec = ["msgspec (>=0.18.5) ; implementation_name == \"cpython\""] -orjson = ["orjson (>=3.9.2) ; implementation_name == \"cpython\""] -pyyaml = ["pyyaml (>=6.0)"] -tomlkit = ["tomlkit (>=0.11.8)"] -ujson = ["ujson (>=5.7.0)"] - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -groups = ["main", "dev"] -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] -markers = {main = "platform_system == \"Windows\"", dev = "platform_system == \"Windows\" or sys_platform == \"win32\""} - -[[package]] -name = "fine-python-aksem" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_module_exports = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_module_exports"} - -[package.source] -type = "git" -url = "https://github.com/Aksem/fine_python_aksem.git" -reference = "HEAD" -resolved_reference = "56ce22c3fb1228a6e85d1a8727a0fa74787608d9" - -[[package]] -name = "fine-python-ast" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main", "dev"] -files = [ - {file = "fine_python_ast-0.1.0-py3-none-any.whl", hash = "sha256:3dcdcdc40ed89e0b90686f2ad5d358d8edba622a5de4c1f52f2f0787dcc4e07d"}, - {file = "fine_python_ast-0.1.0.tar.gz", hash = "sha256:ebc68aef7d0379f8771f610e436f6075b7c299a8895f1b9b7769fd038f95397e"}, -] - -[package.dependencies] -finecode_extension_api = "0.1.0" - -[[package]] -name = "fine-python-black" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_black-0.1.0-py3-none-any.whl", hash = "sha256:27a012123783e4217222546e37280660e5a4948cdd3aa12d7fae7a3ce21a875d"}, - {file = "fine_python_black-0.1.0.tar.gz", hash = "sha256:ce300e897b4d819abe4754177cd5b81d29b2d4d04233942135edc1a8ed234bf7"}, -] - -[package.dependencies] -black = ">=25.1.0,<26.0.0" -finecode_extension_api = "0.1.0" - -[[package]] -name = "fine-python-flake8" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_flake8-0.1.0-py3-none-any.whl", hash = "sha256:7ed7641505936f334396631f779953a13ae18c8f207a8258d722e50fa452d792"}, - {file = "fine_python_flake8-0.1.0.tar.gz", hash = "sha256:ccba9a1ec41f5f3aa756efa63bd64650237ad63d3098aedf673e9c254e502914"}, -] - -[package.dependencies] -fine_python_ast = "0.1.0" -finecode_extension_api = "0.1.0" -flake8 = ">=7.1.2,<8.0.0" -types-flake8 = ">=7.1.0.20241020,<8.0.0.0" - -[[package]] -name = "fine-python-format" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_format-0.1.0-py3-none-any.whl", hash = "sha256:26315bc8ae5a4830efd9ee41ab3e220beead52c0702cc6f82df720e59dbfbfc2"}, - {file = "fine_python_format-0.1.0.tar.gz", hash = "sha256:8d8031316abed4761d096c2a0c100c8d7cc6d391ea386149ef625964ab80d0d2"}, -] - -[package.dependencies] -fine_python_black = "0.1.0" -fine_python_isort = "0.1.0" - -[[package]] -name = "fine-python-isort" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_isort-0.1.0-py3-none-any.whl", hash = "sha256:cbd6cd5502d65122e9f6461758f78db8d9e5628ab97c41a67ee6ef85a3526c8e"}, - {file = "fine_python_isort-0.1.0.tar.gz", hash = "sha256:64468a96b49663226b422885b25de7c22c24f6dafef6c25c1d02ea6e49662b53"}, -] - -[package.dependencies] -finecode_extension_api = "0.1.0" -isort = ">=5.13,<6" - -[[package]] -name = "fine-python-lint" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_lint-0.1.0-py3-none-any.whl", hash = "sha256:180517a54a38ab4942bf51611d03a9afd3668e8d11f59e289444c2e1756434de"}, - {file = "fine_python_lint-0.1.0.tar.gz", hash = "sha256:597660e54fe4fa4024b54f0050cdc378c48d0a03fd2938d1c0ae60204a8160d8"}, -] - -[package.dependencies] -fine_python_flake8 = "0.1.0" -fine_python_mypy = "0.1.0" -flake8-bugbear = ">=24.12.12,<25.0.0" - -[[package]] -name = "fine-python-module-exports" -version = "0.1.0" -description = "" -optional = false -python-versions = ">= 3.11, < 3.14" -groups = ["dev"] -files = [] -develop = false - -[package.dependencies] -fine_python_ast = "0.1.0" -finecode_extension_api = "0.1.0" - -[package.source] -type = "git" -url = "https://github.com/finecode-dev/finecode.git" -reference = "HEAD" -resolved_reference = "191730dcfdb08f610064163dd680c9a501c0f5ba" -subdirectory = "extensions/fine_python_module_exports" - -[[package]] -name = "fine-python-mypy" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main"] -files = [ - {file = "fine_python_mypy-0.1.0-py3-none-any.whl", hash = "sha256:cf1df00ad835fb85aa26480210a08ff963ffa560db123a62adea4a10a3684563"}, - {file = "fine_python_mypy-0.1.0.tar.gz", hash = "sha256:ece18604bdff098c3fd154cd138af74d82276fec20a1ae7ad03114427688e6f6"}, -] - -[package.dependencies] -finecode_extension_api = "0.1.0" -mypy = ">=1.15,<2.0" - -[[package]] -name = "finecode" -version = "0.2.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["dev"] -files = [ - {file = "finecode-0.2.0-py3-none-any.whl", hash = "sha256:42e4980a219a91e9c8a84e51d5df3f7c43d160230bb0fb6001a3e4f28a42041c"}, - {file = "finecode-0.2.0.tar.gz", hash = "sha256:149001825d27403e18c935f67b710184cea3cf3b846283996a595fabcc41d67e"}, -] - -[package.dependencies] -click = "==8.1.*" -finecode_extension_api = "0.1.0" -loguru = "==0.7.*" -ordered-set = "==4.1.*" -platformdirs = "==4.3.*" -pydantic = "==2.10.*" -pygls = "2.0.0-a2" -tomlkit = "==0.11.*" -watchdog = "==4.0.*" - -[[package]] -name = "finecode-dev-common-preset" -version = "0.1.0" -description = "" -optional = false -python-versions = ">=3.11, < 3.14" -groups = ["dev"] -files = [] -develop = true - -[package.dependencies] -fine_python_aksem = {git = "https://github.com/Aksem/fine_python_aksem.git"} -fine_python_recommended = {git = "https://github.com/finecode-dev/finecode.git", subdirectory = "presets/fine_python_recommended"} - -[package.source] -type = "directory" -url = "../../finecode_dev_common_preset" - -[[package]] -name = "finecode-extension-api" -version = "0.1.0" -description = "" -optional = false -python-versions = "<3.14,>=3.11" -groups = ["main", "dev"] -files = [ - {file = "finecode_extension_api-0.1.0-py3-none-any.whl", hash = "sha256:55d4448a1a2f7224c3fdf05879fa9782246c0a85dc1dfb17543374fd808c2b5b"}, - {file = "finecode_extension_api-0.1.0.tar.gz", hash = "sha256:dee16c180e4cd318f71bf7a94b6ae425667153f8fb62630ab60db9b034f45595"}, -] - -[package.dependencies] -pydantic = ">=2.10.6,<3.0.0" -typing-extensions = ">=4.12.2,<5.0.0" - -[[package]] -name = "flake8" -version = "7.2.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343"}, - {file = "flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.13.0,<2.14.0" -pyflakes = ">=3.3.0,<3.4.0" - -[[package]] -name = "flake8-bugbear" -version = "24.12.12" -description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." -optional = false -python-versions = ">=3.8.1" -groups = ["main"] -files = [ - {file = "flake8_bugbear-24.12.12-py3-none-any.whl", hash = "sha256:1b6967436f65ca22a42e5373aaa6f2d87966ade9aa38d4baf2a1be550767545e"}, - {file = "flake8_bugbear-24.12.12.tar.gz", hash = "sha256:46273cef0a6b6ff48ca2d69e472f41420a42a46e24b2a8972e4f0d6733d12a64"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -flake8 = ">=6.0.0" - -[package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -groups = ["main"] -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "loguru" -version = "0.7.3" -description = "Python logging made (stupidly) simple" -optional = false -python-versions = "<4.0,>=3.5" -groups = ["dev"] -files = [ - {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, - {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, -] - -[package.dependencies] -colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} -win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} - -[package.extras] -dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==v0.910) ; python_version < \"3.6\"", "mypy (==v0.971) ; python_version == \"3.6\"", "mypy (==v1.13.0) ; python_version >= \"3.8\"", "mypy (==v1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] - -[[package]] -name = "lsprotocol" -version = "2024.0.0b1" -description = "Python types for Language Server Protocol." -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "lsprotocol-2024.0.0b1-py3-none-any.whl", hash = "sha256:93785050ac155ae2be16b1ebfbd74c214feb3d3ef77b10399ce941e5ccef6ebd"}, - {file = "lsprotocol-2024.0.0b1.tar.gz", hash = "sha256:d3667fb70894d361aa6c495c5c8a1b2e6a44be65ff84c21a9cbb67ebfb4830fd"}, -] - -[package.dependencies] -attrs = ">=21.3.0" -cattrs = "!=23.2.1" - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -groups = ["main"] -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "mypy" -version = "1.15.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, - {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b"}, - {file = "mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3"}, - {file = "mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b"}, - {file = "mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f"}, - {file = "mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e"}, - {file = "mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c"}, - {file = "mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f"}, - {file = "mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd"}, - {file = "mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464"}, - {file = "mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee"}, - {file = "mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e"}, - {file = "mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445"}, - {file = "mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5"}, - {file = "mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036"}, - {file = "mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357"}, - {file = "mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078"}, - {file = "mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5"}, - {file = "mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b"}, - {file = "mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2"}, - {file = "mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980"}, - {file = "mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e"}, - {file = "mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.1.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505"}, - {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, -] - -[[package]] -name = "ordered-set" -version = "4.1.0" -description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, - {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"}, -] - -[package.extras] -dev = ["black", "mypy", "pytest"] - -[[package]] -name = "packaging" -version = "25.0" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, - {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -groups = ["main"] -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.3.8" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.9" -groups = ["main", "dev"] -files = [ - {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, - {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.14.1)"] - -[[package]] -name = "pycodestyle" -version = "2.13.0" -description = "Python style guide checker" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9"}, - {file = "pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae"}, -] - -[[package]] -name = "pydantic" -version = "2.10.6" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, - {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.27.2" -typing-extensions = ">=4.12.2" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] - -[[package]] -name = "pydantic-core" -version = "2.27.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, - {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pyflakes" -version = "3.3.2" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a"}, - {file = "pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b"}, -] - -[[package]] -name = "pygls" -version = "2.0.0a2" -description = "A pythonic generic language server (pronounced like 'pie glass')" -optional = false -python-versions = ">=3.9" -groups = ["dev"] -files = [ - {file = "pygls-2.0.0a2-py3-none-any.whl", hash = "sha256:b202369321409343aa6440d73111d9fa0c22e580466ff1c7696b8358bb91f243"}, - {file = "pygls-2.0.0a2.tar.gz", hash = "sha256:03e00634ed8d989918268aaa4b4a0c3ab857ea2d4ee94514a52efa5ddd6d5d9f"}, -] - -[package.dependencies] -cattrs = ">=23.1.2" -lsprotocol = "2024.0.0b1" - -[package.extras] -ws = ["websockets (>=13.0)"] - -[[package]] -name = "tomlkit" -version = "0.11.8" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.7" -groups = ["dev"] -files = [ - {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, - {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, -] - -[[package]] -name = "types-flake8" -version = "7.2.0.20250330" -description = "Typing stubs for flake8" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "types_flake8-7.2.0.20250330-py3-none-any.whl", hash = "sha256:af31590a269586309b80a439c94e59359e139e17475a8fc8d3c426ab01a40547"}, - {file = "types_flake8-7.2.0.20250330.tar.gz", hash = "sha256:481e5c914a26fabd23e85704ad055f2716f9238740bfe6fe77259c2533cb970c"}, -] - -[package.dependencies] -types-pyflakes = "*" - -[[package]] -name = "types-pyflakes" -version = "3.3.2.20250511" -description = "Typing stubs for pyflakes" -optional = false -python-versions = ">=3.9" -groups = ["main"] -files = [ - {file = "types_pyflakes-3.3.2.20250511-py3-none-any.whl", hash = "sha256:85802fdd0b64d3553ef12ac0ba02d85c4bbd38747579c544e6bb005ec455becf"}, - {file = "types_pyflakes-3.3.2.20250511.tar.gz", hash = "sha256:d0ef58f9ec15eab2a9e427814f48587be4eb2752a8ae7dec201d65086f50ace2"}, -] - -[[package]] -name = "typing-extensions" -version = "4.13.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -groups = ["main", "dev"] -files = [ - {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, - {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, -] - -[[package]] -name = "watchdog" -version = "4.0.2" -description = "Filesystem events monitoring" -optional = false -python-versions = ">=3.8" -groups = ["dev"] -files = [ - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ede7f010f2239b97cc79e6cb3c249e72962404ae3865860855d5cbe708b0fd22"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a2cffa171445b0efa0726c561eca9a27d00a1f2b83846dbd5a4f639c4f8ca8e1"}, - {file = "watchdog-4.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c50f148b31b03fbadd6d0b5980e38b558046b127dc483e5e4505fcef250f9503"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7c7d4bf585ad501c5f6c980e7be9c4f15604c7cc150e942d82083b31a7548930"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:914285126ad0b6eb2258bbbcb7b288d9dfd655ae88fa28945be05a7b475a800b"}, - {file = "watchdog-4.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:984306dc4720da5498b16fc037b36ac443816125a3705dfde4fd90652d8028ef"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1cdcfd8142f604630deef34722d695fb455d04ab7cfe9963055df1fc69e6727a"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d7ab624ff2f663f98cd03c8b7eedc09375a911794dfea6bf2a359fcc266bff29"}, - {file = "watchdog-4.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:132937547a716027bd5714383dfc40dc66c26769f1ce8a72a859d6a48f371f3a"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:cd67c7df93eb58f360c43802acc945fa8da70c675b6fa37a241e17ca698ca49b"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcfd02377be80ef3b6bc4ce481ef3959640458d6feaae0bd43dd90a43da90a7d"}, - {file = "watchdog-4.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:980b71510f59c884d684b3663d46e7a14b457c9611c481e5cef08f4dd022eed7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:aa160781cafff2719b663c8a506156e9289d111d80f3387cf3af49cedee1f040"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f6ee8dedd255087bc7fe82adf046f0b75479b989185fb0bdf9a98b612170eac7"}, - {file = "watchdog-4.0.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0b4359067d30d5b864e09c8597b112fe0a0a59321a0f331498b013fb097406b4"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:770eef5372f146997638d737c9a3c597a3b41037cfbc5c41538fc27c09c3a3f9"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eeea812f38536a0aa859972d50c76e37f4456474b02bd93674d1947cf1e39578"}, - {file = "watchdog-4.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b2c45f6e1e57ebb4687690c05bc3a2c1fb6ab260550c4290b8abb1335e0fd08b"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:10b6683df70d340ac3279eff0b2766813f00f35a1d37515d2c99959ada8f05fa"}, - {file = "watchdog-4.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f7c739888c20f99824f7aa9d31ac8a97353e22d0c0e54703a547a218f6637eb3"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c100d09ac72a8a08ddbf0629ddfa0b8ee41740f9051429baa8e31bb903ad7508"}, - {file = "watchdog-4.0.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f5315a8c8dd6dd9425b974515081fc0aadca1d1d61e078d2246509fd756141ee"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:2d468028a77b42cc685ed694a7a550a8d1771bb05193ba7b24006b8241a571a1"}, - {file = "watchdog-4.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f15edcae3830ff20e55d1f4e743e92970c847bcddc8b7509bcd172aa04de506e"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:936acba76d636f70db8f3c66e76aa6cb5136a936fc2a5088b9ce1c7a3508fc83"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:e252f8ca942a870f38cf785aef420285431311652d871409a64e2a0a52a2174c"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:0e83619a2d5d436a7e58a1aea957a3c1ccbf9782c43c0b4fed80580e5e4acd1a"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:88456d65f207b39f1981bf772e473799fcdc10801062c36fd5ad9f9d1d463a73"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:32be97f3b75693a93c683787a87a0dc8db98bb84701539954eef991fb35f5fbc"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:c82253cfc9be68e3e49282831afad2c1f6593af80c0daf1287f6a92657986757"}, - {file = "watchdog-4.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c0b14488bd336c5b1845cee83d3e631a1f8b4e9c5091ec539406e4a324f882d8"}, - {file = "watchdog-4.0.2-py3-none-win32.whl", hash = "sha256:0d8a7e523ef03757a5aa29f591437d64d0d894635f8a50f370fe37f913ce4e19"}, - {file = "watchdog-4.0.2-py3-none-win_amd64.whl", hash = "sha256:c344453ef3bf875a535b0488e3ad28e341adbd5a9ffb0f7d62cefacc8824ef2b"}, - {file = "watchdog-4.0.2-py3-none-win_ia64.whl", hash = "sha256:baececaa8edff42cd16558a639a9b0ddf425f93d892e8392a56bf904f5eff22c"}, - {file = "watchdog-4.0.2.tar.gz", hash = "sha256:b4dfbb6c49221be4535623ea4474a4d6ee0a9cef4a80b20c28db4d858b64e270"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - -[[package]] -name = "win32-setctime" -version = "1.2.0" -description = "A small Python utility to set file creation time on Windows" -optional = false -python-versions = ">=3.5" -groups = ["dev"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, - {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, -] - -[package.extras] -dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] - -[metadata] -lock-version = "2.1" -python-versions = ">=3.11, < 3.14" -content-hash = "da67317bd7ee70f58ec5be079ab16636dfdc7086e21d68af48d4d5bc37c1cebc" diff --git a/presets/fine_python_recommended/pyproject.toml b/presets/fine_python_recommended/pyproject.toml index 099c5b4..30cd230 100644 --- a/presets/fine_python_recommended/pyproject.toml +++ b/presets/fine_python_recommended/pyproject.toml @@ -1,16 +1,15 @@ [project] name = "fine-python-recommended" -version = "0.1.0" +version = "0.2.0" description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" requires-python = ">=3.11, < 3.14" -dependencies = ["fine_python_format==0.1.0", "fine_python_lint==0.1.0"] - -[tool.poetry.group.dev.dependencies] -finecode = { version = "0.2.0" } -finecode_dev_common_preset = { path = "../../finecode_dev_common_preset", develop = true } +dependencies = ["fine_python_format==0.2.*", "fine_python_lint==0.2.*"] [build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +requires = ["setuptools>=64"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.package-data] +fine_python_recommended = ["preset.toml"] diff --git a/presets/fine_python_recommended/setup.py b/presets/fine_python_recommended/setup.py new file mode 100644 index 0000000..1eb7ee2 --- /dev/null +++ b/presets/fine_python_recommended/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="fine_python_recommended", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/pyproject.toml b/pyproject.toml index 6bed5d7..2230c04 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,6 @@ [project] name = "finecode" -version = "0.2.0" -# dynamic version from setuptools-scm is not compatible with poetry, because it requires explicit version in pyproject.toml. Will be used after migration from poetry. -# dynamic = ["version"] +dynamic = ["version"] description = "" authors = [{ name = "Vladyslav Hnatiuk", email = "aders1234@gmail.com" }] readme = "README.md" @@ -15,31 +13,35 @@ dependencies = [ "pydantic==2.10.*", "platformdirs==4.3.*", "pygls==2.0.0-a2", - "finecode_extension_api==0.1.0", + "finecode_extension_api==0.3.*", + "finecode_extension_runner==0.3.*", "ordered-set==4.1.*", + "mcp==1.9.*", + "fine_python_virtualenv==0.1.*", + "fine_python_pip==0.1.*", ] [dependency-groups] -dev_workspace = ["build==1.2.2.post1"] +dev_workspace = ["build==1.2.2.post1", "finecode==0.3.0", "debugpy==1.8.*"] +dev = [{ include-group = "runtime" }, "pytest==7.4.*", "debugpy==1.8.*"] +dev_no_runtime = [ + "finecode_dev_common_preset==0.2.*", + # file_python_import_linter is temporary disabled, because it isn't ported to the new finecode_extension_api yet + # "fine_python_import_linter @ git+https://github.com/finecode-dev/finecode.git#subdirectory=extensions/fine_python_import_linter", +] [build-system] requires = ["setuptools>=64", "setuptools-scm>=8"] build-backend = "setuptools.build_meta" -[tool.poetry] -packages = [{ include = "finecode", from = "src" }] - -[tool.poetry.group.dev.dependencies] -pytest = "^7.4.3" -finecode_dev_common_preset = { path = "./finecode_dev_common_preset", develop = true } -fine_python_import_linter = { git = "https://github.com/finecode-dev/finecode.git", subdirectory = "extensions/fine_python_import_linter" } -anyio = "^4.4.0" -debugpy = "^1.8.9" - +# TODO: add import linter handler to lint action [tool.finecode] presets = [{ source = "finecode_dev_common_preset" }] +[tool.finecode.env.dev_no_runtime.dependencies] +finecode_dev_common_preset = { path = "./finecode_dev_common_preset", editable = true } + [tool.importlinter] root_package = "finecode" include_external_packages = true @@ -49,20 +51,11 @@ id = "wm-layered" name = "WM layered architecture" type = "layers" layers = [ - "finecode.workspace_manager.lsp_server.lsp_server", - "finecode.workspace_manager.lsp_server.services", - "finecode.workspace_manager.domain", + "finecode.lsp_server.lsp_server", + "finecode.lsp_server.services", + "finecode.domain", ] -[[tool.importlinter.contracts]] -id = "er-layered" -name = "ER layered architecture" -type = "layers" -layers = [ - "finecode.extension_runner.lsp_server", - "finecode.extension_runner.services", - "finecode.extension_runner.domain", -] [[tool.importlinter.contracts]] # such check doesn't control whether there are no raw requests in lsp_server, currently this should @@ -70,13 +63,16 @@ layers = [ id = "wm-use-runner-client" name = "WM uses LSP requests only in runner_client and lsp_server, no raw requests in app" type = "forbidden" -source_modules = ["finecode.workspace_manager"] +source_modules = ["finecode"] forbidden_modules = ["lsprotocol"] ignore_imports = [ - "finecode.workspace_manager.runner.runner_client -> lsprotocol", - "finecode.workspace_manager.lsp_server.lsp_server -> lsprotocol", + "finecode.runner.runner_client -> lsprotocol", + "finecode.lsp_server.lsp_server -> lsprotocol", ] [tool.setuptools_scm] version_file = "src/finecode/_version.py" + +[tool.setuptools.package-data] +finecode = ["base_config.toml"] diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..0a949ac --- /dev/null +++ b/setup.py @@ -0,0 +1,67 @@ +import atexit +import shutil +import sys +import tempfile + +from setuptools import setup +from setuptools.command.build import build +from setuptools.command.build_ext import build_ext +from setuptools.command.build_py import build_py +from setuptools.command.egg_info import egg_info + +# Create a single temp directory for all build operations +_TEMP_BUILD_DIR = None + + +def get_temp_build_dir(pkg_name): + global _TEMP_BUILD_DIR + if _TEMP_BUILD_DIR is None: + _TEMP_BUILD_DIR = tempfile.mkdtemp(prefix=f"{pkg_name}_build_") + atexit.register(lambda: shutil.rmtree(_TEMP_BUILD_DIR, ignore_errors=True)) + return _TEMP_BUILD_DIR + + +class TempDirBuildMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.build_base = temp_dir + + +class TempDirEggInfoMixin: + def initialize_options(self): + super().initialize_options() + temp_dir = get_temp_build_dir(self.distribution.get_name()) + self.egg_base = temp_dir + + +class CustomBuild(TempDirBuildMixin, build): + pass + + +class CustomBuildPy(TempDirBuildMixin, build_py): + pass + + +class CustomBuildExt(TempDirBuildMixin, build_ext): + pass + + +class CustomEggInfo(TempDirEggInfoMixin, egg_info): + def initialize_options(self): + # Don't use temp dir for editable installs + if "--editable" in sys.argv or "-e" in sys.argv: + egg_info.initialize_options(self) + else: + super().initialize_options() + + +setup( + name="finecode", + cmdclass={ + "build": CustomBuild, + "build_py": CustomBuildPy, + "build_ext": CustomBuildExt, + "egg_info": CustomEggInfo, + }, +) diff --git a/src/finecode/__main__.py b/src/finecode/__main__.py index 758e4b0..487132e 100644 --- a/src/finecode/__main__.py +++ b/src/finecode/__main__.py @@ -1,4 +1,4 @@ -from finecode.workspace_manager import cli as wm_cli +from finecode import cli as wm_cli if __name__ == "__main__": wm_cli.cli() diff --git a/src/finecode/workspace_manager/app_dirs.py b/src/finecode/app_dirs.py similarity index 100% rename from src/finecode/workspace_manager/app_dirs.py rename to src/finecode/app_dirs.py diff --git a/src/finecode/base_config.toml b/src/finecode/base_config.toml new file mode 100644 index 0000000..520d83d --- /dev/null +++ b/src/finecode/base_config.toml @@ -0,0 +1,86 @@ +[tool.finecode.action.prepare_envs] +source = "finecode_extension_api.actions.prepare_envs.PrepareEnvsAction" + +[[tool.finecode.action.prepare_envs.handlers]] +name = "prepare_envs_dump_configs" +source = "finecode_extension_runner.action_handlers.PrepareEnvsReadConfigsHandler" +env = "dev_workspace" + + +[[tool.finecode.action.prepare_envs.handlers]] +name = "prepare_envs_install_deps" +source = "finecode_extension_runner.action_handlers.PrepareEnvsInstallDepsHandler" +env = "dev_workspace" + + +# preparing dev workspaces doesn't need dumping config for two reasons: +# - dependencies in `dev_workspace` are expected to be simple and installable +# without dump +# - dumping is modifiable as action, so it can be correctly done only in +# dev_workspace env of the project and we just create it here, it doesn't +# exist yet +[tool.finecode.action.prepare_dev_workspaces_envs] +source = "finecode_extension_api.actions.prepare_envs.PrepareEnvsAction" + +[[tool.finecode.action.prepare_dev_workspaces_envs.handlers]] +name = "prepare_venvs" +source = "fine_python_virtualenv.VirtualenvPrepareEnvHandler" +env = "dev_workspace" +dependencies = ["fine_python_virtualenv==0.1.*"] + +[[tool.finecode.action.prepare_dev_workspaces_envs.handlers]] +name = "prepare_envs_read_configs" +source = "finecode_extension_runner.action_handlers.PrepareEnvsReadConfigsHandler" +env = "dev_workspace" + + +[[tool.finecode.action.prepare_dev_workspaces_envs.handlers]] +name = "prepare_envs_install_deps" +source = "finecode_extension_runner.action_handlers.PrepareEnvsInstallDepsHandler" +env = "dev_workspace" + + +[tool.finecode.action.prepare_runners] +source = "finecode_extension_api.actions.prepare_runners.PrepareRunnersAction" + +[[tool.finecode.action.prepare_runners.handlers]] +name = "prepare_runners_venvs" +source = "fine_python_virtualenv.VirtualenvPrepareRunnersHandler" +env = "dev_workspace" +dependencies = ["fine_python_virtualenv==0.1.*"] + +[[tool.finecode.action.prepare_runners.handlers]] +name = "prepare_runners_read_configs" +source = "finecode_extension_runner.action_handlers.PrepareRunnersReadConfigsHandler" +env = "dev_workspace" + + +[[tool.finecode.action.prepare_runners.handlers]] +name = "prepare_runners_install_runner_and_presets" +source = "finecode_extension_runner.action_handlers.PrepareRunnersInstallRunnerAndPresetsHandler" +env = "dev_workspace" + + +[tool.finecode.action.dump_config] +source = "finecode_extension_api.actions.dump_config.DumpConfigAction" + +[[tool.finecode.action.dump_config.handlers]] +name = "dump_config" +source = "finecode_extension_runner.action_handlers.DumpConfigHandler" +env = "dev_workspace" + + +[[tool.finecode.action.dump_config.handlers]] +name = "dump_config_save" +source = "finecode_extension_runner.action_handlers.DumpConfigSaveHandler" +env = "dev_workspace" + + +[tool.finecode.action.install_deps_in_env] +source = "finecode_extension_api.actions.install_deps_in_env.InstallDepsInEnvAction" + +[[tool.finecode.action.install_deps_in_env.handlers]] +name = "install_deps_with_pip" +source = "fine_python_pip.PipInstallDepsInEnvHandler" +env = "dev_workspace" +dependencies = ["fine_python_pip==0.1.*"] diff --git a/src/finecode/workspace_manager/cli.py b/src/finecode/cli.py similarity index 64% rename from src/finecode/workspace_manager/cli.py rename to src/finecode/cli.py index 95b66f0..3d23742 100644 --- a/src/finecode/workspace_manager/cli.py +++ b/src/finecode/cli.py @@ -1,16 +1,18 @@ import asyncio +import json import os import pathlib +import typing import sys import click from loguru import logger -import finecode.workspace_manager.main as workspace_manager -from finecode import communication_utils -from finecode.workspace_manager import logger_utils, user_messages -from finecode.workspace_manager.cli_app import run as run_cmd -from finecode.workspace_manager.cli_app import dump_config as dump_config_cmd +import finecode.main as workspace_manager +from finecode import communication_utils, logger_utils, user_messages +from finecode.cli_app import dump_config as dump_config_cmd +from finecode.cli_app import prepare_envs as prepare_envs_cmd +from finecode.cli_app import run as run_cmd @click.group() @@ -31,6 +33,10 @@ def cli(): ... @click.option( "--port", "port", default=None, type=int, help="Port for TCP and WS server" ) +@click.option("--mcp", "mcp", is_flag=True, default=False) +@click.option( + "--mcp-port", "mcp_port", default=None, type=int, help="Port for MCP server" +) def start_api( trace: bool, debug: bool, @@ -39,6 +45,8 @@ def start_api( stdio: bool, host: str | None, port: int | None, + mcp: bool, + mcp_port: int | None, ): if debug is True: import debugpy @@ -73,10 +81,23 @@ def start_api( workspace_manager.start_sync(comm_type=comm_type, host=host, port=port, trace=trace) -async def show_user_message( - message: str, message_type: str -) -> None: - logger.log(message_type, message) +async def show_user_message(message: str, message_type: str) -> None: + # user messages in CLI are not needed because CLI outputs own messages + ... + + +def deserialize_action_payload(raw_payload: dict[str, str]) -> dict[str, typing.Any]: + deserialized_payload = {} + for key, value in raw_payload.items(): + if value.startswith('{') and value.endswith('}'): + try: + deserialized_value = json.loads(value) + except json.JSONDecodeError: + deserialized_value = value + else: + deserialized_value = value + deserialized_payload[key] = deserialized_value + return deserialized_payload @cli.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True)) @@ -130,7 +151,7 @@ def run(ctx) -> None: sys.exit(1) # action payload - action_payload: dict[str, str] = {} + action_payload: dict[str, typing.Any] = {} for arg in args[processed_args_count:]: if not arg.startswith("--"): click.echo( @@ -147,15 +168,17 @@ def run(ctx) -> None: sys.exit(1) else: arg_name, arg_value = arg[2:].split("=") - action_payload[arg_name] = arg_value + arg_name = arg_name.replace('-', '_') + action_payload[arg_name] = arg_value.strip('"').strip("'") processed_args_count += 1 user_messages._notification_sender = show_user_message + deserialized_payload= deserialize_action_payload(action_payload) try: output, return_code = asyncio.run( run_cmd.run_actions( - workdir_path, projects, actions_to_run, action_payload, concurrently + workdir_path, projects, actions_to_run, deserialized_payload, concurrently ) ) click.echo(output) @@ -166,18 +189,50 @@ def run(ctx) -> None: except Exception as exception: logger.exception(exception) click.echo("Unexpected error, see logs in file for more details", err=True) + sys.exit(2) + + +@cli.command() +@click.option("--trace", "trace", is_flag=True, default=False) +@click.option("--debug", "debug", is_flag=True, default=False) +@click.option("--recreate", "recreate", is_flag=True, default=False) +def prepare_envs(trace: bool, debug: bool, recreate: bool) -> None: + """ + `prepare-envs` should be called from workspace/project root directory. + """ + # idea: project parameter to allow to run from other directories? + if debug is True: + import debugpy + + try: + debugpy.listen(5680) + debugpy.wait_for_client() + except Exception as e: + logger.info(e) + + logger_utils.init_logger(trace=trace, stdout=True) + user_messages._notification_sender = show_user_message + + try: + asyncio.run( + prepare_envs_cmd.prepare_envs( + workdir_path=pathlib.Path(os.getcwd()), recreate=recreate + ) + ) + except prepare_envs_cmd.PrepareEnvsFailed as exception: + click.echo(exception.args[0], err=True) sys.exit(1) + except Exception as exception: + logger.exception(exception) + click.echo("Unexpected error, see logs in file for more details", err=True) + sys.exit(2) @cli.command() @click.option("--trace", "trace", is_flag=True, default=False) @click.option("--debug", "debug", is_flag=True, default=False) @click.option("--project", "project", type=str) -def dump_config( - trace: bool, - debug: bool, - project: str | None -): +def dump_config(trace: bool, debug: bool, project: str | None): if debug is True: import debugpy @@ -190,11 +245,16 @@ def dump_config( if project is None: click.echo("--project parameter is required", err=True) return - + logger_utils.init_logger(trace=trace, stdout=True) + user_messages._notification_sender = show_user_message try: - asyncio.run(dump_config_cmd.dump_config(workdir_path=pathlib.Path(os.getcwd()), project_name=project)) + asyncio.run( + dump_config_cmd.dump_config( + workdir_path=pathlib.Path(os.getcwd()), project_name=project + ) + ) except dump_config_cmd.DumpFailed as exception: click.echo(exception.message, err=True) sys.exit(1) diff --git a/src/finecode/cli_app/__init__.py b/src/finecode/cli_app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/finecode/workspace_manager/cli_app/dump_config.py b/src/finecode/cli_app/dump_config.py similarity index 55% rename from src/finecode/workspace_manager/cli_app/dump_config.py rename to src/finecode/cli_app/dump_config.py index 8e41e2d..3e0742d 100644 --- a/src/finecode/workspace_manager/cli_app/dump_config.py +++ b/src/finecode/cli_app/dump_config.py @@ -3,9 +3,9 @@ from loguru import logger -from finecode.workspace_manager import context, services -from finecode.workspace_manager.config import read_configs, dump_configs -from finecode.workspace_manager.runner import manager as runner_manager +from finecode import context, services +from finecode.config import config_models, read_configs +from finecode.runner import manager as runner_manager class DumpFailed(Exception): @@ -27,7 +27,19 @@ async def dump_config(workdir_path: pathlib.Path, project_name: str): for project_dir_path, project in ws_context.ws_projects.items() if project.name == project_name } - + + # read configs without presets, this is required to be able to start runners in + # the next step + for project in ws_context.ws_projects.values(): + try: + await read_configs.read_project_config( + project=project, ws_context=ws_context, resolve_presets=False + ) + except config_models.ConfigurationError as exception: + raise DumpFailed( + f"Reading project configs(without presets) in {project.dir_path} failed: {exception.message}" + ) + # start runner to init project config try: try: @@ -41,16 +53,23 @@ async def dump_config(workdir_path: pathlib.Path, project_name: str): # Some tools like IDE extensions for syntax highlighting rely on # file name. Keep file name of config the same and save in subdirectory project_dir_path = list(ws_context.ws_projects.keys())[0] - dump_dir_path = project_dir_path / 'finecode_config_dump' - dump_file_path = dump_dir_path / 'pyproject.toml' - + dump_dir_path = project_dir_path / "finecode_config_dump" + dump_file_path = dump_dir_path / "pyproject.toml" project_raw_config = ws_context.ws_projects_raw_configs[project_dir_path] - raw_config_str = dump_configs.dump_config(project_raw_config) + project_def = ws_context.ws_projects[project_dir_path] - os.makedirs(dump_dir_path, exist_ok=True) - with open(dump_file_path, 'w') as dump_file: - dump_file.write(raw_config_str) - + await services.run_action( + action_name="dump_config", + params={ + "source_file_path": project_def.def_path, + "project_raw_config": project_raw_config, + "target_file_path": dump_file_path, + }, + project_def=project_def, + ws_context=ws_context, + result_format=services.RunResultFormat.STRING, + preprocess_payload=False, + ) logger.info(f"Dumped config into {dump_file_path}") finally: services.on_shutdown(ws_context) diff --git a/src/finecode/cli_app/prepare_envs.py b/src/finecode/cli_app/prepare_envs.py new file mode 100644 index 0000000..cf62d7c --- /dev/null +++ b/src/finecode/cli_app/prepare_envs.py @@ -0,0 +1,277 @@ +import pathlib +import shutil + +from loguru import logger + +from finecode import context, domain, proxy_utils, services +from finecode.cli_app import run as run_cli +from finecode.config import collect_actions, config_models, read_configs +from finecode.runner import manager as runner_manager + + +class PrepareEnvsFailed(Exception): ... + + +async def prepare_envs(workdir_path: pathlib.Path, recreate: bool) -> None: + # similar to `run_actions`, but with certain differences: + # - prepare_envs doesn't support presets because `dev_no_runtime` env most + # probably doesn't exist yet + # - we don't need to check missing actions, because prepare_envs is a builtin action + # and it exists always + ws_context = context.WorkspaceContext([workdir_path]) + await read_configs.read_projects_in_dir( + dir_path=workdir_path, ws_context=ws_context + ) + + # `prepare_envs` can be run only from workspace/project root. Validate this + if workdir_path not in ws_context.ws_projects: + raise PrepareEnvsFailed( + "prepare_env can be run only from workspace/project root" + ) + + invalid_projects = [ + project + for project in ws_context.ws_projects.values() + if project.status == domain.ProjectStatus.CONFIG_INVALID + ] + if len(invalid_projects) > 0: + raise PrepareEnvsFailed( + f"Projects have invalid configuration: {invalid_projects}" + ) + + # prepare envs only in projects with valid configurations and which use finecode + projects = [ + project + for project in ws_context.ws_projects.values() + if project.status == domain.ProjectStatus.CONFIG_VALID + ] + + # Collect actions in relevant projects + for project in projects: + try: + await read_configs.read_project_config( + project=project, ws_context=ws_context, resolve_presets=False + ) + collect_actions.collect_actions( + project_path=project.dir_path, ws_context=ws_context + ) + except config_models.ConfigurationError as exception: + raise PrepareEnvsFailed( + f"Reading project config and collecting actions in {project.dir_path} failed: {exception.message}" + ) + + try: + # try to start runner in 'dev_workspace' env of each project. If venv doesn't + # exist or doesn't work, recreate it by running actions in the current env. + if recreate: + remove_dev_workspace_envs(projects=projects, workdir_path=workdir_path) + + await check_or_recreate_all_dev_workspace_envs( + projects=projects, + workdir_path=workdir_path, + recreate=recreate, + ws_context=ws_context, + ) + + # now all 'dev_workspace' envs are valid, run 'prepare_runners' in them to create + # venvs and install runners and presets in them. This is required to be able to + # resolve presets which can contain additional dependency configurations. + # Only then run `prepare_envs` to install dependencies in each subproject. + + actions_by_projects: dict[pathlib.Path, list[str]] = { + project.dir_path: ["prepare_runners"] for project in projects + } + # action payload can be kept empty because it will be filled in payload preprocessor + action_payload: dict[str, str | bool] = {"recreate": recreate} + + try: + await proxy_utils.start_required_environments( + actions_by_projects, ws_context + ) + except proxy_utils.StartingEnvironmentsFailed as exception: + raise PrepareEnvsFailed( + f"Failed to start environments for running 'prepare_runners': {exception.message}" + ) + + try: + (result_output, result_return_code) = ( + await run_cli.run_actions_in_all_projects( + actions_by_projects, action_payload, ws_context, concurrently=True + ) + ) + except run_cli.RunFailed as error: + logger.error(error.message) + result_output = error.message + result_return_code = 1 + + if result_return_code != 0: + raise PrepareEnvsFailed(result_output) + + # reread projects configs, now with resolved presets + # to be able to resolve presets, start dev_no_runtime runners first + try: + await runner_manager.start_runners_with_presets( + projects=projects, ws_context=ws_context + ) + except runner_manager.RunnerFailedToStart as exception: + raise PrepareEnvsFailed( + f"Starting runners with presets failed: {exception.message}" + ) + + for project in projects: + try: + await read_configs.read_project_config( + project=project, ws_context=ws_context + ) + collect_actions.collect_actions( + project_path=project.dir_path, ws_context=ws_context + ) + except config_models.ConfigurationError as exception: + raise PrepareEnvsFailed( + f"Rereading project config with presets and collecting actions in {project.dir_path} failed: {exception.message}" + ) + + actions_by_projects: dict[pathlib.Path, list[str]] = { + project.dir_path: ["prepare_envs"] for project in projects + } + # action payload can be kept empty because it will be filled in payload preprocessor + action_payload: dict[str, str | bool] = {"recreate": recreate} + + try: + (result_output, result_return_code) = ( + await run_cli.run_actions_in_all_projects( + actions_by_projects, action_payload, ws_context, concurrently=True + ) + ) + except run_cli.RunFailed as error: + logger.error(error.message) + result_output = error.message + result_return_code = 1 + + if result_return_code != 0: + raise PrepareEnvsFailed(result_output) + finally: + services.on_shutdown(ws_context) + + +def remove_dev_workspace_envs( + projects: list[domain.Project], workdir_path: pathlib.Path +) -> None: + for project in projects: + if project.dir_path == workdir_path: + # skip removing `dev_workspace` env of the current project, because user + # is responsible for keeping it correct + continue + + runner_manager.remove_runner_venv( + runner_dir=project.dir_path, env_name="dev_workspace" + ) + + +async def check_or_recreate_all_dev_workspace_envs( + projects: list[domain.Project], + workdir_path: pathlib.Path, + recreate: bool, + ws_context: context.WorkspaceContext, +) -> None: + # NOTE: this function can start new extensions runner, don't forget to call + # on_shutdown if you use it + projects_dirs_with_valid_envs: list[pathlib.Path] = [] + projects_dirs_with_invalid_envs: list[pathlib.Path] = [] + + for project in projects: + if project.dir_path == workdir_path: + # skip checking `dev_workspace` env of the current project, because user + # is responsible for keeping it correct + continue + + runner_is_valid = await runner_manager.check_runner( + runner_dir=project.dir_path, env_name="dev_workspace" + ) + if runner_is_valid: + projects_dirs_with_valid_envs.append(project.dir_path) + else: + if recreate: + logger.trace( + f"Recreate runner for env 'dev_workspace' in project '{project.name}'" + ) + else: + logger.warning( + f"Runner for env 'dev_workspace' in project '{project.name}' is invalid, recreate it" + ) + projects_dirs_with_invalid_envs.append(project.dir_path) + + # to recreate dev_workspace env, run `prepare_envs` in runner of current project + current_project_dir_path = ws_context.ws_dirs_paths[0] + current_project = ws_context.ws_projects[current_project_dir_path] + try: + runner = await runner_manager.start_runner( + project_def=current_project, env_name="dev_workspace", ws_context=ws_context + ) + except runner_manager.RunnerFailedToStart as exception: + # TODO + raise exception + + envs = [] + + # run pip install in dev_workspace even if env exists to make sure that correct + # dependencies are installed + for project_dir_path in projects_dirs_with_valid_envs: + if project_dir_path == workdir_path: + # skip installation of dependencies in `dev_workspace` env of the + # current project, because user is responsible for keeping them + # up-to-date + continue + + # dependencies in `dev_workspace` should be simple and installable without + # dumping + envs.append( + { + "name": "dev_workspace", + "venv_dir_path": project_dir_path / ".venvs" / "dev_workspace", + "project_def_path": project_dir_path / "pyproject.toml", + } + ) + + if len(projects_dirs_with_invalid_envs) > 0: + invalid_envs = [] + + for project_dir_path in projects_dirs_with_invalid_envs: + # dependencies in `dev_workspace` should be simple and installable without + # dumping + invalid_envs.append( + { + "name": "dev_workspace", + "venv_dir_path": project_dir_path / ".venvs" / "dev_workspace", + "project_def_path": project_dir_path / "pyproject.toml", + } + ) + + # remove existing invalid envs + for env_info in invalid_envs: + if env_info["venv_dir_path"].exists(): + logger.trace(f"{env_info['venv_dir_path']} was invalid, remove it") + shutil.rmtree(env_info["venv_dir_path"]) + + envs += invalid_envs + + try: + action_result = await services.run_action( + action_name="prepare_dev_workspaces_envs", + params={ + "envs": envs, + }, + project_def=current_project, + ws_context=ws_context, + result_format=services.RunResultFormat.STRING, + preprocess_payload=False, + ) + except services.ActionRunFailed as exception: + raise PrepareEnvsFailed( + f"'prepare_dev_workspaces_env' failed in {current_project.name}: {exception.message}" + ) + + if action_result.return_code != 0: + raise PrepareEnvsFailed( + f"'prepare_dev_workspaces_env' ended in {current_project.name} with return code {action_result.return_code}: {action_result.result}" + ) diff --git a/src/finecode/workspace_manager/cli_app/run.py b/src/finecode/cli_app/run.py similarity index 65% rename from src/finecode/workspace_manager/cli_app/run.py rename to src/finecode/cli_app/run.py index e52c461..f5be9c4 100644 --- a/src/finecode/workspace_manager/cli_app/run.py +++ b/src/finecode/cli_app/run.py @@ -6,12 +6,15 @@ import ordered_set from loguru import logger -from finecode.workspace_manager import context, domain, services -from finecode.workspace_manager.config import read_configs -from finecode.workspace_manager.runner import manager as runner_manager +from finecode import context, domain, proxy_utils, services +from finecode.config import collect_actions, config_models, read_configs +from finecode.runner import manager as runner_manager +from finecode.runner import runner_info -class RunFailed(Exception): ... +class RunFailed(Exception): + def __init__(self, message: str) -> None: + self.message = message async def run_actions( @@ -35,20 +38,107 @@ async def run_actions( if project.name in projects_names } + # make sure all projects use finecode + config_problem_found = False + for project in ws_context.ws_projects.values(): + if project.status != domain.ProjectStatus.CONFIG_VALID: + if project.status == domain.ProjectStatus.NO_FINECODE: + logger.error( + f"You asked to run action in project '{project.name}', but finecode is not used in it(=there is no 'dev_workspace' environment with 'finecode' package in it)" + ) + config_problem_found = True + elif project.status == domain.ProjectStatus.CONFIG_INVALID: + logger.error( + f"You asked to run action in project '{project.name}', but its configuration is invalid(see logs above for more details)" + ) + config_problem_found = True + else: + logger.error( + f"You asked to run action in project '{project.name}', but it has unexpected status: {project.status}" + ) + config_problem_found = True + + if config_problem_found: + raise RunFailed( + "There is a problem with configuration. See previous messages for more details" + ) + else: + # filter out packages that don't use finecode + ws_context.ws_projects = { + project_dir_path: project + for project_dir_path, project in ws_context.ws_projects.items() + if project.status != domain.ProjectStatus.NO_FINECODE + } + + # check that configuration of packages that use finecode is valid + config_problem_found = False + for project in ws_context.ws_projects.values(): + if project.status == domain.ProjectStatus.CONFIG_VALID: + continue + elif project.status == domain.ProjectStatus.CONFIG_INVALID: + logger.error( + f"Project '{project.name}' has invalid config, see messages above for more details" + ) + config_problem_found = True + else: + logger.error( + f"Project '{project.name}' has unexpected status: {project.status}" + ) + config_problem_found = True + + if config_problem_found: + raise RunFailed( + "There is a problem with configuration. See previous messages for more details" + ) + + projects: list[domain.Project] = [] + if projects_names is not None: + projects = get_projects_by_names(projects_names, ws_context, workdir_path) + else: + projects = list(ws_context.ws_projects.values()) + + # first read configs without presets to be able to start runners with presets + for project in projects: + try: + await read_configs.read_project_config( + project=project, ws_context=ws_context, resolve_presets=False + ) + collect_actions.collect_actions( + project_path=project.dir_path, ws_context=ws_context + ) + except config_models.ConfigurationError as exception: + raise RunFailed( + f"Reading project config and collecting actions in {project.dir_path} failed: {exception.message}" + ) + try: + # 1. Start runners with presets to be able to resolve presets. Presets are + # required to be able to collect all actions, actions handlers and configs. try: - await runner_manager.update_runners(ws_context) + await runner_manager.start_runners_with_presets(projects, ws_context) except runner_manager.RunnerFailedToStart as exception: raise RunFailed( f"One or more projects are misconfigured, runners for them didn't" f" start: {exception.message}. Check logs for details." ) + except Exception as exception: + logger.error("Unexpected exception:") + logger.exception(exception) + + # 2. Collect actions in relevant projects + for project in projects: + try: + await read_configs.read_project_config( + project=project, ws_context=ws_context + ) + collect_actions.collect_actions( + project_path=project.dir_path, ws_context=ws_context + ) + except config_models.ConfigurationError as exception: + raise RunFailed(f"Found configuration problem: {exception.message}") actions_by_projects: dict[pathlib.Path, list[str]] = {} if projects_names is not None: - projects: list[domain.Project] = get_projects_by_names( - projects_names, ws_context, workdir_path - ) # check that all projects have all actions to detect problem and provide # feedback as early as possible actions_set: ordered_set.OrderedSet[str] = ordered_set.OrderedSet(actions) @@ -67,6 +157,15 @@ async def run_actions( # actions will be run in all projects inside actions_by_projects = find_projects_with_actions(ws_context, actions) + try: + await proxy_utils.start_required_environments( + actions_by_projects, ws_context, update_config_in_running_runners=True + ) + except proxy_utils.StartingEnvironmentsFailed as exception: + raise RunFailed( + f"Failed to start environments for running actions: {exception.message}" + ) + return await run_actions_in_all_projects( actions_by_projects, action_payload, ws_context, concurrently ) @@ -105,8 +204,8 @@ def find_projects_with_actions( for project in ws_context.ws_projects.values(): project_actions_names = [action.name for action in project.actions] # find which of requested actions are available in the project - action_to_run_in_project = ( - actions_set & ordered_set.OrderedSet(project_actions_names) + action_to_run_in_project = actions_set & ordered_set.OrderedSet( + project_actions_names ) relevant_actions_in_project = list(action_to_run_in_project) if len(relevant_actions_in_project) > 0: @@ -215,9 +314,13 @@ async def run_actions_in_running_project( ) run_tasks.append(run_task) except ExceptionGroup as eg: - for error in eg: - logger.exception(error) - raise RunFailed(f"Running of action {action_name} failed") + for exception in eg.exceptions: + if isinstance(exception, services.ActionRunFailed): + logger.error(f"{exception.message} in {project.name}") + else: + logger.error("Unexpected exception:") + logger.exception(exception) + raise RunFailed(f"Running of actions {actions} failed") for idx, run_task in enumerate(run_tasks): run_result = run_task.result() @@ -237,6 +340,8 @@ async def run_actions_in_running_project( result_format=services.RunResultFormat.STRING, ) except Exception as error: + # TODO: which are expected here? + logger.error("Unexpected exception") logger.exception(error) raise RunFailed(f"Running of action {action_name} failed") @@ -271,6 +376,7 @@ async def run_actions_in_all_projects( project_handler_tasks.append(project_task) except ExceptionGroup as eg: for exception in eg.exceptions: + # TODO: merge all in one? raise exception result_output: str = "" @@ -287,7 +393,9 @@ async def run_actions_in_all_projects( result_output += "\n" if run_in_many_projects: - result_output += f"{click.style(str(project_dir_path), bold=True, underline=True)}\n" + result_output += ( + f"{click.style(str(project_dir_path), bold=True, underline=True)}\n" + ) for action_name, action_result in result_by_action.items(): if run_many_actions: diff --git a/src/finecode/config/__init__.py b/src/finecode/config/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/finecode/workspace_manager/config/collect_actions.py b/src/finecode/config/collect_actions.py similarity index 50% rename from src/finecode/workspace_manager/config/collect_actions.py rename to src/finecode/config/collect_actions.py index 7ee0543..06bf796 100644 --- a/src/finecode/workspace_manager/config/collect_actions.py +++ b/src/finecode/config/collect_actions.py @@ -1,9 +1,9 @@ from pathlib import Path from typing import Any -import finecode.workspace_manager.config.config_models as config_models -import finecode.workspace_manager.context as context -import finecode.workspace_manager.domain as domain +import finecode.config.config_models as config_models +import finecode.context as context +import finecode.domain as domain def collect_actions( @@ -29,29 +29,52 @@ def collect_actions( actions = _collect_actions_in_config(config) project.actions = actions + action_handler_configs = _collect_action_handler_configs_in_config(config) + project.action_handler_configs = action_handler_configs + return actions +def _collect_action_handler_configs_in_config( + config: dict[str, Any], +) -> dict[str, dict[str, Any]]: + action_handlers_configs = config["tool"]["finecode"].get("action_handler", []) + action_handler_config_by_source: dict[str, dict[str, Any]] = {} + for handler_def in action_handlers_configs: + if "source" not in handler_def or not isinstance(handler_def["source"], str): + raise config_models.ConfigurationError( + "Action handler definition expected to have a 'source' field(to identify handler) and it should be a string" + ) + + handler_config = handler_def.get("config", None) + if handler_config is not None: + action_handler_config_by_source[handler_def["source"]] = handler_config + + return action_handler_config_by_source + + def _collect_actions_in_config( config: dict[str, Any], ) -> list[domain.Action]: actions: list[domain.Action] = [] - for action_name, action_def_raw in ( config["tool"]["finecode"].get("action", {}).items() ): - # TODO: handle validation errors - action_def = config_models.ActionDefinition(**action_def_raw) + + try: + action_def = config_models.ActionDefinition(**action_def_raw) + except config_models.ValidationError as exception: + raise config_models.ConfigurationError(str(exception)) + new_action = domain.Action( name=action_name, handlers=[ domain.ActionHandler( name=handler.name, source=handler.source, - config=config["tool"]["finecode"] - .get("action_handler", {}) - .get(handler.name, {}) - .get("config", {}), + config=handler.config or {}, + env=handler.env, + dependencies=handler.dependencies, ) for handler in action_def.handlers ], diff --git a/src/finecode/workspace_manager/config/config_models.py b/src/finecode/config/config_models.py similarity index 64% rename from src/finecode/workspace_manager/config/config_models.py rename to src/finecode/config/config_models.py index 96b8cbf..5c9b172 100644 --- a/src/finecode/workspace_manager/config/config_models.py +++ b/src/finecode/config/config_models.py @@ -1,6 +1,6 @@ from typing import Any -from pydantic import BaseModel +from pydantic import BaseModel, ValidationError class FinecodePresetDefinition(BaseModel): @@ -17,14 +17,6 @@ class FinecodeViewDefinition(BaseModel): source: str -class FinecodeConfig(BaseModel): - presets: list[FinecodePresetDefinition] = [] - actions: list[FinecodeActionDefinition] = [] - views: list[FinecodeViewDefinition] = [] - action: dict[str, dict[str, Any]] = {} - action_handler: dict[str, dict[str, Any]] = {} - - class PresetDefinition(BaseModel): extends: list[FinecodePresetDefinition] = [] @@ -32,10 +24,13 @@ class PresetDefinition(BaseModel): class ActionHandlerDefinition(BaseModel): name: str source: str + env: str + dependencies: list[str] = [] + config: dict[str, Any] | None = None class ActionDefinition(BaseModel): - source: str | None = None + source: str handlers: list[ActionHandlerDefinition] = [] config: dict[str, Any] | None = None @@ -43,3 +38,8 @@ class ActionDefinition(BaseModel): class ViewDefinition(BaseModel): name: str source: str + + +class ConfigurationError(Exception): + def __init__(self, message: str) -> None: + self.message = message diff --git a/src/finecode/config/read_configs.py b/src/finecode/config/read_configs.py new file mode 100644 index 0000000..e5f9302 --- /dev/null +++ b/src/finecode/config/read_configs.py @@ -0,0 +1,570 @@ +from importlib import metadata +from pathlib import Path +from typing import Any, NamedTuple + +from loguru import logger +from tomlkit import loads as toml_loads + +from finecode import context, domain, user_messages +from finecode.config import config_models +from finecode.runner import runner_client, runner_info + + +async def read_projects_in_dir( + dir_path: Path, ws_context: context.WorkspaceContext +) -> list[domain.Project]: + # Find all projects in directory + # `dir_path` expected to be absolute path + logger.trace(f"Read directories in {dir_path}") + new_projects: list[domain.Project] = [] + def_files_generator = dir_path.rglob("pyproject.toml") + for def_file in def_files_generator: + # ignore definition files in `__testdata__` directory, projects in test data + # can be started only in tests, not from outside + # TODO: make configurable? + # path to definition file relative to workspace directory in which this + # definition was found + def_file_rel_dir_path = def_file.relative_to(dir_path) + if "__testdata__" in def_file_rel_dir_path.parts: + logger.debug( + f"Skip '{def_file}' because it is in test data and it is not a test session" + ) + continue + if def_file.parent.name == "finecode_config_dump": + logger.debug( + f"Skip '{def_file}' because it is config dump, not real project config" + ) + continue + + status = domain.ProjectStatus.CONFIG_VALID + actions: list[domain.Action] | None = None + + with open(def_file, "rb") as pyproject_file: + project_def = toml_loads(pyproject_file.read()).value + + dependency_groups = project_def.get("dependency-groups", {}) + dev_workspace_group = dependency_groups.get("dev_workspace", []) + finecode_in_dev_workspace = any( + dep for dep in dev_workspace_group if get_dependency_name(dep) == "finecode" + ) + if not finecode_in_dev_workspace: + status = domain.ProjectStatus.NO_FINECODE + actions = [] + + new_project = domain.Project( + name=def_file.parent.name, + dir_path=def_file.parent, + def_path=def_file, + status=status, + actions=actions, + env_configs={}, + ) + ws_context.ws_projects[def_file.parent] = new_project + new_projects.append(new_project) + return new_projects + + +def get_dependency_name(dependency_str: str) -> str: + # simplified way for now: find the first character which is not allowed in package + # name + for idx, ch in enumerate(dependency_str): + if not ch.isalnum() and ch not in "-_": + return dependency_str[:idx] + + # dependency can consist also just of package name without version + return dependency_str + + +def read_env_configs(project_config: dict[str, Any]) -> dict[str, domain.EnvConfig]: + env_configs = {} + env_config_section = ( + project_config.get("tool", {}).get("finecode", {}).get("env", {}) + ) + for env_name, env_raw_config in env_config_section.items(): + if "runner" in env_raw_config: + runner_raw_config = env_raw_config["runner"] + if "debug" in runner_raw_config: + debug = runner_raw_config["debug"] + runner_config = domain.RunnerConfig(debug=debug) + env_config = domain.EnvConfig(runner_config=runner_config) + env_configs[env_name] = env_config + + # add default configs + deps_groups = project_config.get("dependency-groups", {}) + for group_name in deps_groups.keys(): + if group_name not in env_configs: + runner_config = domain.RunnerConfig(debug=False) + env_config = domain.EnvConfig(runner_config=runner_config) + env_configs[group_name] = env_config + + return env_configs + + +async def read_project_config( + project: domain.Project, + ws_context: context.WorkspaceContext, + resolve_presets: bool = True, +) -> None: + # this function requires running project extension runner to get configuration + # from it + if project.def_path.name == "pyproject.toml": + with open(project.def_path, "rb") as pyproject_file: + # TODO: handle error if toml is invalid + project_def = toml_loads(pyproject_file.read()).value + # TODO: validate that finecode is installed? + + base_config_path = Path(__file__).parent.parent / "base_config.toml" + # TODO: cache instead of reading each time + with open(base_config_path, "r") as base_config_file: + base_config = toml_loads(base_config_file.read()).value + project_config = {} + _merge_projects_configs( + project_config, project.def_path, base_config, base_config_path + ) + + finecode_raw_config = project_def.get("tool", {}).get("finecode", None) + if finecode_raw_config and resolve_presets: + try: + presets = [ + config_models.FinecodePresetDefinition(**raw_preset) + for raw_preset in finecode_raw_config.get("presets", []) + ] + except config_models.ValidationError as exception: + raise config_models.ConfigurationError(str(exception)) + + # all presets expected to be in `dev_no_runtime` environment + project_runners = ws_context.ws_projects_extension_runners[project.dir_path] + # TODO: can it be the case that there is no such runner? + dev_no_runtime_runner = project_runners["dev_no_runtime"] + new_config = await collect_config_from_py_presets( + presets_sources=[preset.source for preset in presets], + def_path=project.def_path, + runner=dev_no_runtime_runner, + ) + if new_config is not None: + _merge_projects_configs( + project_config, project.def_path, new_config, project.def_path + ) + + _merge_projects_configs( + project_config, project.def_path, project_def, project.def_path + ) + # `_merge_projects_configs` merges only finecode config. Copy all other keys as + # is + for key, value in project_def.items(): + if key != "tool": + project_config[key] = value + tool_raw_config = project_def.get("tool", None) + if tool_raw_config is not None: + if "tool" not in project_config: + project_config["tool"] = {} + project_tool_config = project_config["tool"] + for key, value in tool_raw_config.items(): + if key != "finecode": + project_tool_config[key] = value + + # add runtime dependency group if it's not explicitly declared + add_runtime_dependency_group_if_new(project_config) + + add_extension_runner_to_dependencies(project_config) + + merge_handlers_dependencies_into_groups(project_config) + + ws_context.ws_projects_raw_configs[project.dir_path] = project_config + + env_configs = read_env_configs(project_config=project_config) + project.env_configs = env_configs + else: + logger.info( + f"Project definition of type {project.def_path.name} is not supported yet" + ) + + +class PresetToProcess(NamedTuple): + source: str + project_def_path: Path + + +async def get_preset_project_path( + preset: PresetToProcess, def_path: Path, runner: runner_info.ExtensionRunnerInfo +) -> Path | None: + logger.trace(f"Get preset project path: {preset.source}") + + try: + resolve_path_result = await runner_client.resolve_package_path( + runner, preset.source + ) + except runner_client.BaseRunnerRequestException as error: + await user_messages.error(f"Failed to get preset project path: {error.message}") + return None + try: + preset_project_path = Path(resolve_path_result["packagePath"]) + except KeyError: + raise ValueError(f"Preset source cannot be resolved: {preset.source}") + + logger.trace(f"Got: {preset.source} -> {preset_project_path}") + return preset_project_path + + +def read_preset_config( + config_path: Path, preset_id: str +) -> tuple[dict[str, Any], config_models.PresetDefinition]: + # preset_id is used only for logs to make them more useful + logger.trace(f"Read preset config: {preset_id}") + if not config_path.exists(): + # if package is installed in editable mode, we will get path to root directory + # of the package, not to source directory. In such case check both flat and + # src layouts of the package + config_dir_path = config_path.parent + flat_path_to_src = config_dir_path / preset_id + if flat_path_to_src.exists(): + config_path = flat_path_to_src / "preset.toml" + else: + src_path_to_src = config_dir_path / "src" / preset_id + if src_path_to_src.exists(): + config_path = src_path_to_src / "preset.toml" + else: + raise config_models.ConfigurationError( + f"preset.toml not found in project '{preset_id}'" + ) + + with open(config_path, "rb") as preset_toml_file: + preset_toml = toml_loads(preset_toml_file.read()).value + + try: + presets = preset_toml["tool"]["finecode"]["presets"] + except KeyError: + presets = [] + + preset_config = config_models.PresetDefinition(extends=presets) + + logger.trace(f"Reading preset config finished: {preset_id}") + return (preset_toml, preset_config) + + +async def collect_config_from_py_presets( + presets_sources: list[str], def_path: Path, runner: runner_info.ExtensionRunnerInfo +) -> dict[str, Any] | None: + config: dict[str, Any] | None = None + processed_presets: set[str] = set() + presets_to_process: set[PresetToProcess] = set( + [ + PresetToProcess(source=preset_source, project_def_path=def_path) + for preset_source in presets_sources + ] + ) + while len(presets_to_process) > 0: + preset = presets_to_process.pop() + processed_presets.add(preset.source) + + preset_project_path = await get_preset_project_path( + preset=preset, def_path=def_path, runner=runner + ) + if preset_project_path is None: + logger.trace(f"Path of preset {preset.source} not found") + raise config_models.ConfigurationError( + f"Path of preset {preset.source} in project {def_path.parent} not found" + ) + + preset_toml_path = preset_project_path / "preset.toml" + preset_toml, preset_config = read_preset_config(preset_toml_path, preset.source) + if config is None: + config = preset_toml + else: + _merge_projects_configs(config, def_path, preset_toml, preset_project_path) + new_presets_sources = ( + set([extend.source for extend in preset_config.extends]) - processed_presets + ) + for new_preset_source in new_presets_sources: + presets_to_process.add( + PresetToProcess( + source=new_preset_source, + project_def_path=def_path, + ) + ) + + return config + + +def _merge_object_array_by_key( + existing_array: list[dict[str, Any]], + new_array: list[dict[str, Any]], + key_field: str, +) -> None: + """ + Merges object arrays by a specified key field. + + For each object in new_array: + - If an object with the same key_field value exists in existing_array, deep merge them + - If no object with that key_field value exists, append the new object + + Args: + existing_array: The array to merge into + new_array: The array to merge from + key_field: The field name to use as the merge key (e.g., 'name', 'source') + """ + # Create a lookup map for existing objects by the key field + existing_by_key = {} + for i, obj in enumerate(existing_array): + if isinstance(obj, dict) and key_field in obj: + existing_by_key[obj[key_field]] = i + + # Process each new object + for new_obj in new_array: + if not isinstance(new_obj, dict) or key_field not in new_obj: + # If the object doesn't have the key field, just append it + existing_array.append(new_obj) + continue + + obj_key = new_obj[key_field] + if obj_key in existing_by_key: + # Merge with existing object + existing_index = existing_by_key[obj_key] + existing_obj = existing_array[existing_index] + _deep_merge_dicts(existing_obj, new_obj) + else: + # Add new object + existing_array.append(new_obj) + + +def _deep_merge_dicts(target: dict[str, Any], source: dict[str, Any]) -> None: + """ + Deep merge source dict into target dict. + Arrays are replaced entirely (not merged), following TOML semantics. + """ + for key, value in source.items(): + if key in target and isinstance(target[key], dict) and isinstance(value, dict): + _deep_merge_dicts(target[key], value) + else: + target[key] = value + + +def _merge_projects_configs( + config1: dict[str, Any], + config1_filepath: Path, + config2: dict[str, Any], + config2_filepath: Path, +) -> None: + # merge config2 in config1 without overwriting + if "tool" not in config1: + config1["tool"] = {} + if "finecode" not in config1["tool"]: + config1["tool"]["finecode"] = {} + + tool_finecode_config1 = config1["tool"]["finecode"] + tool_finecode_config2 = config2.get("tool", {}).get("finecode", {}) + + for key, value in tool_finecode_config2.items(): + if key == "action": + # first process actions explicitly to merge correct configs + assert isinstance(value, dict) + if key not in tool_finecode_config1: + tool_finecode_config1[key] = {} + for action_name, action_info in value.items(): + if action_name not in tool_finecode_config1[key]: + # new action, just add as it is + tool_finecode_config1[key][action_name] = action_info + else: + # action with the same name, merge + if "config" in action_info: + if "config" not in tool_finecode_config1[key][action_name]: + tool_finecode_config1[key][action_name]["config"] = {} + + action_config = tool_finecode_config1[key][action_name][ + "config" + ] + action_config.update(action_info["config"]) + + # Handle handlers array merge by name + if "handlers" in action_info: + if "handlers" not in tool_finecode_config1[key][action_name]: + tool_finecode_config1[key][action_name]["handlers"] = [] + + existing_handlers = tool_finecode_config1[key][action_name][ + "handlers" + ] + new_handlers = action_info["handlers"] + + # Merge handlers by name + _merge_object_array_by_key( + existing_handlers, new_handlers, "name" + ) + elif key == "action_handler": + # Handle action_handler array merge by source + if key not in tool_finecode_config1: + tool_finecode_config1[key] = [] + + existing_action_handlers = tool_finecode_config1[key] + # Ensure value is a list + if isinstance(value, list): + new_action_handlers = value + # Merge action_handlers by source + _merge_object_array_by_key( + existing_action_handlers, new_action_handlers, "source" + ) + else: + # If it's not a list, just set it directly (shouldn't happen with TOML arrays but be safe) + tool_finecode_config1[key] = value + elif key == "env": + if "env" not in tool_finecode_config1: + tool_finecode_config1["env"] = {} + + all_envs_config1 = tool_finecode_config1["env"] + + for env_name, env_config2 in value.items(): + if env_name not in all_envs_config1: + all_envs_config1[env_name] = env_config2 + else: + # merge env configs + env_config1 = all_envs_config1[env_name] + if "dependencies" in env_config2: + if "dependencies" not in env_config1: + env_config1["dependencies"] = env_config2["dependencies"] + else: + # merge dependencies + env_config1_deps = env_config1["dependencies"] + for dependency_name, dependency in env_config2[ + "dependencies" + ].items(): + if dependency_name not in env_config1_deps: + env_config1_deps[dependency_name] = dependency + else: + if "path" in dependency: + new_path = dependency["path"] + if new_path.startswith("."): + abs_path = ( + config2_filepath.parent / new_path + ) + new_rel_path = abs_path.relative_to( + config1_filepath.parent + ) + new_path = new_rel_path.as_posix() + env_config1_deps[dependency_name][ + "path" + ] = new_path + if "editable" in dependency: + env_config1_deps[dependency_name][ + "editable" + ] = dependency["editable"] + if "runner" in env_config2: + if "runner" not in env_config1: + env_config1["runner"] = {} + env_config1_runner = env_config1["runner"] + env_config2_runner = env_config2["runner"] + + if "debug" in env_config2_runner: + env_config1_runner["debug"] = env_config2_runner["debug"] + elif key in config1: + tool_finecode_config1[key].update(value) + else: + tool_finecode_config1[key] = value + + +def add_action_to_config_if_new( + raw_config: dict[str, Any], action: domain.Action +) -> None: + # adds action to raw config if it is not defined yet. Existing action will be not + # overwritten + tool_config = add_or_get_dict_key_value(raw_config, "tool", {}) + finecode_config = add_or_get_dict_key_value(tool_config, "finecode", {}) + action_config = add_or_get_dict_key_value(finecode_config, "action", {}) + if action.name not in action_config: + action_raw_dict = { + "source": action.source, + "handlers": [handler_to_dict(handler) for handler in action.handlers], + } + action_config[action.name] = action_raw_dict + + # example of action definition: + # [tool.finecode.action.text_document_inlay_hint] + # source = "finecode_extension_api.actions.ide.text_document_inlay_hint.TextDocumentInlayHintAction" + # handlers = [ + # { name = 'module_exports_inlay_hint', source = 'fine_python_module_exports.extension.get_document_inlay_hints', env = "dev_no_runtime", dependencies = [ + # "fine_python_module_exports @ git+https://github.com/finecode-dev/finecode.git#subdirectory=extensions/fine_python_module_exports", + # ] }, + # ] + + +def add_or_get_dict_key_value( + dict_obj: dict[str, Any], key: str, default_value: Any +) -> Any: + if key not in dict_obj: + value = default_value + dict_obj[key] = value + else: + value = dict_obj[key] + + return value + + +def handler_to_dict(handler: domain.ActionHandler) -> dict[str, str | list[str]]: + return { + "name": handler.name, + "source": handler.source, + "env": handler.env, + "dependencies": handler.dependencies, + } + + +def add_runtime_dependency_group_if_new(project_config: dict[str, Any]) -> None: + runtime_dependencies = project_config.get("project", {}).get("dependencies", []) + + deps_groups = add_or_get_dict_key_value(project_config, "dependency-groups", {}) + if "runtime" not in deps_groups: + deps_groups["runtime"] = runtime_dependencies + + +def merge_handlers_dependencies_into_groups(project_config: dict[str, Any]) -> None: + # tool.finecode.action..handlers[x].dependencies + actions_dict = project_config.get("tool", {}).get("finecode", {}).get("action", {}) + if "dependency-groups" not in project_config: + project_config["dependency-groups"] = {} + deps_groups = project_config["dependency-groups"] + + for action_info in actions_dict.values(): + action_handlers = action_info.get("handlers", []) + + for handler in action_handlers: + handler_env = handler.get("env", None) + if handler_env is None: + logger.warning(f"Handler {handler} has no env, skip it") + continue + deps = handler.get("dependencies", []) + + if handler_env not in deps_groups: + deps_groups[handler_env] = [] + + env_deps = deps_groups[handler_env] + # should we remove duplicates here? + env_deps += deps + + # remove duplicates in dependencies because multiple handlers can have the same + # dependencies / be from the same package + for group_name in deps_groups.keys(): + deps_list = deps_groups[group_name] + + # another possibility would be to use `ordered_set.OrderedSet`, but dependency + # list can contain not only strings, but also dictionaries like + # `{ 'include-group': 'runtime' }` which are not hashable + unique_deps = [] + for dep in deps_list: + if dep not in unique_deps: + unique_deps.append(dep) + + deps_groups[group_name] = unique_deps + + +def add_extension_runner_to_dependencies(project_config: dict[str, Any]) -> None: + try: + deps_groups = project_config["dependency-groups"] + except KeyError: + return + + finecode_version = metadata.version("finecode") + + for group_name, group_packages in deps_groups.items(): + if group_name == "dev_workspace": + # skip `dev_workspace` because it contains finecode already + continue + + group_packages.append(f"finecode_extension_runner == {finecode_version}") diff --git a/src/finecode/workspace_manager/context.py b/src/finecode/context.py similarity index 85% rename from src/finecode/workspace_manager/context.py rename to src/finecode/context.py index 2cef2e7..ffbcca1 100644 --- a/src/finecode/workspace_manager/context.py +++ b/src/finecode/context.py @@ -4,10 +4,10 @@ from pathlib import Path from typing import TYPE_CHECKING, Any -from finecode.workspace_manager import domain +from finecode import domain if TYPE_CHECKING: - from finecode.workspace_manager.runner.runner_info import ExtensionRunnerInfo + from finecode.runner.runner_info import ExtensionRunnerInfo @dataclass @@ -19,7 +19,8 @@ class WorkspaceContext: ws_projects: dict[Path, domain.Project] = field(default_factory=dict) # ws_projects_raw_configs: dict[Path, dict[str, Any]] = field(default_factory=dict) - ws_projects_extension_runners: dict[Path, ExtensionRunnerInfo] = field( + # > + ws_projects_extension_runners: dict[Path, dict[str, ExtensionRunnerInfo]] = field( default_factory=dict ) ignore_watch_paths: set[Path] = field(default_factory=set) diff --git a/src/finecode/workspace_manager/domain.py b/src/finecode/domain.py similarity index 59% rename from src/finecode/workspace_manager/domain.py rename to src/finecode/domain.py index 0f98307..4229e93 100644 --- a/src/finecode/workspace_manager/domain.py +++ b/src/finecode/domain.py @@ -4,6 +4,8 @@ from enum import Enum, auto from pathlib import Path +import ordered_set + class Preset: def __init__(self, source: str) -> None: @@ -11,10 +13,19 @@ def __init__(self, source: str) -> None: class ActionHandler: - def __init__(self, name: str, source: str, config: dict[str, typing.Any]): + def __init__( + self, + name: str, + source: str, + config: dict[str, typing.Any], + env: str, + dependencies: list[str], + ): self.name: str = name self.source: str = source self.config: dict[str, typing.Any] = config + self.env: str = env + self.dependencies: list[str] = dependencies class Action: @@ -38,6 +49,7 @@ def __init__( dir_path: Path, def_path: Path, status: ProjectStatus, + env_configs: dict[str, EnvConfig], actions: list[Action] | None = None, ) -> None: self.name = name @@ -47,6 +59,12 @@ def __init__( # None means actions were not collected yet # if project.status is RUNNING, then actions are not None self.actions = actions + # config by handler source + self.action_handler_configs: dict[str, dict[str, typing.Any]] = {} + # config by env name + # it always contains configs for all environments, even if user hasn't provided + # one explicitly(=there is a default config) + self.env_configs: dict[str, EnvConfig] = env_configs def __str__(self) -> str: return ( @@ -56,14 +74,35 @@ def __str__(self) -> str: def __repr__(self) -> str: return str(self) + @property + def envs(self) -> list[str]: + if self.actions is None: + raise ValueError("Actions are not collected yet") + + all_envs_set = ordered_set.OrderedSet([]) + for action in self.actions: + action_envs = [handler.env for handler in action.handlers] + all_envs_set |= ordered_set.OrderedSet(action_envs) + + return list(all_envs_set) + class ProjectStatus(Enum): - READY = auto() + CONFIG_INVALID = auto() + # config valid, but no finecode in project NO_FINECODE = auto() - NO_FINECODE_SH = auto() - RUNNER_FAILED = auto() - RUNNING = auto() - EXITED = auto() + # config valid and finecode is used in project + CONFIG_VALID = auto() + + +class RunnerConfig: + def __init__(self, debug: bool) -> None: + self.debug = debug + + +class EnvConfig: + def __init__(self, runner_config: RunnerConfig) -> None: + self.runner_config = runner_config RootActions = list[str] @@ -102,4 +141,6 @@ class PartialResult(typing.NamedTuple): "Action", "Project", "TextDocumentInfo", + "RunnerConfig", + "EnvConfig", ] diff --git a/src/finecode/extension_runner/README.md b/src/finecode/extension_runner/README.md deleted file mode 100644 index 97514be..0000000 --- a/src/finecode/extension_runner/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# FineCode Python Extension Runner - -## Development Notes - -- extension server could use tcp communication with workspace manager, but for some reason it didn't work in first tries: it blocked the server, client connection was accepted, but no requests were processed. - -## Data Provider - -dataKind: PythonPackageList - -provider: PythonPackageListProvider - -all data must be versioned - -providers calculate data either automatically or on demand diff --git a/src/finecode/extension_runner/bootstrap.py b/src/finecode/extension_runner/bootstrap.py deleted file mode 100644 index 4a5e4cd..0000000 --- a/src/finecode/extension_runner/bootstrap.py +++ /dev/null @@ -1,90 +0,0 @@ -""" -Requirements on DI in FineCode: -- using interfaces in functions and injecting implementations -- all implementations are singletons --- but technically it should be possible to add non-singletons -- default container is known -- default container can be customized at one place, no dynamic changes -""" - -from typing import Any, Callable, Type, TypeVar - -try: - import fine_python_ast -except ImportError: - fine_python_ast = None - -try: - import fine_python_mypy -except ImportError: - fine_python_mypy = None - -from finecode.extension_runner import global_state -from finecode.extension_runner.impls import ( - command_runner, - file_manager, - inmemory_cache, - loguru_logger, -) -from finecode_extension_api import code_action -from finecode_extension_api.interfaces import ( - icache, - icommandrunner, - ifilemanager, - ilogger, -) - -container: dict[str, Any] = {} - - -def bootstrap(get_document_func: Callable, save_document_func: Callable): - # logger_instance = loguru_logger.LoguruLogger() - logger_instance = loguru_logger.get_logger() - command_runner_instance = command_runner.CommandRunner(logger=logger_instance) - file_manager_instance = file_manager.FileManager( - docs_owned_by_client=global_state.runner_context.docs_owned_by_client, - get_document_func=get_document_func, - save_document_func=save_document_func, - logger=logger_instance, - ) - cache_instance = inmemory_cache.InMemoryCache( - file_manager=file_manager_instance, logger=logger_instance - ) - container[ilogger.ILogger] = logger_instance - container[icommandrunner.ICommandRunner] = command_runner_instance - container[ifilemanager.IFileManager] = file_manager_instance - container[icache.ICache] = cache_instance - - # TODO: parameters from config - ... - - -T = TypeVar("T") - - -def get_service_instance(service_type: Type[T]) -> T: - if service_type == code_action.ActionHandlerLifecycle: - return code_action.ActionHandlerLifecycle() - - # singletons - if service_type in container: - return container[service_type] - else: - match service_type: - case fine_python_ast.IPythonSingleAstProvider: - service_instance = fine_python_ast.PythonSingleAstProvider( - file_manager=container[ifilemanager.IFileManager], - cache=container[icache.ICache], - logger=container[ilogger.ILogger], - ) - case fine_python_mypy.IMypySingleAstProvider: - service_instance = fine_python_mypy.MypySingleAstProvider( - file_manager=container[ifilemanager.IFileManager], - cache=container[icache.ICache], - logger=container[ilogger.ILogger], - ) - case _: - raise NotImplementedError(f"No implementation found for {service_type}") - - container[service_type] = service_instance - return service_instance diff --git a/src/finecode/workspace_manager/find_project.py b/src/finecode/find_project.py similarity index 96% rename from src/finecode/workspace_manager/find_project.py rename to src/finecode/find_project.py index bfe0f92..3be854a 100644 --- a/src/finecode/workspace_manager/find_project.py +++ b/src/finecode/find_project.py @@ -2,8 +2,8 @@ from loguru import logger -from finecode.workspace_manager import domain -from finecode.workspace_manager.context import WorkspaceContext +from finecode import domain +from finecode.context import WorkspaceContext class FileNotInWorkspaceException(BaseException): ... diff --git a/src/finecode/finecode_cmd.py b/src/finecode/finecode_cmd.py new file mode 100644 index 0000000..8939437 --- /dev/null +++ b/src/finecode/finecode_cmd.py @@ -0,0 +1,16 @@ +from pathlib import Path + + +def get_venv_dir_path(project_path: Path, env_name: str) -> Path: + venv_dir_path = project_path / ".venvs" / env_name + return venv_dir_path + + +def get_python_cmd(project_path: Path, env_name: str) -> str: + venv_dir_path = get_venv_dir_path(project_path=project_path, env_name=env_name) + venv_python_path = venv_dir_path / "bin" / "python" + + if not venv_python_path.exists(): + raise ValueError(f"{env_name} venv not found in project {project_path}") + + return venv_python_path.as_posix() diff --git a/src/finecode/workspace_manager/logger_utils.py b/src/finecode/logger_utils.py similarity index 95% rename from src/finecode/workspace_manager/logger_utils.py rename to src/finecode/logger_utils.py index b3a7212..19dc4c9 100644 --- a/src/finecode/workspace_manager/logger_utils.py +++ b/src/finecode/logger_utils.py @@ -4,8 +4,8 @@ from loguru import logger -from finecode import logs -from finecode.workspace_manager import app_dirs +from finecode import app_dirs +from finecode_extension_runner import logs def init_logger(trace: bool, stdout: bool = False): diff --git a/src/finecode/lsp_server/__init__.py b/src/finecode/lsp_server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/finecode/workspace_manager/lsp_server/api.proto b/src/finecode/lsp_server/api.proto similarity index 97% rename from src/finecode/workspace_manager/lsp_server/api.proto rename to src/finecode/lsp_server/api.proto index 60fa907..0f594e9 100644 --- a/src/finecode/workspace_manager/lsp_server/api.proto +++ b/src/finecode/lsp_server/api.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package finecode.workspace_manager; +package finecode; message AddWorkspaceDirRequest { string dir_path = 1; diff --git a/src/finecode/lsp_server/endpoints/__init__.py b/src/finecode/lsp_server/endpoints/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/finecode/workspace_manager/lsp_server/endpoints/action_tree.py b/src/finecode/lsp_server/endpoints/action_tree.py similarity index 84% rename from src/finecode/workspace_manager/lsp_server/endpoints/action_tree.py rename to src/finecode/lsp_server/endpoints/action_tree.py index 955184a..ec0de72 100644 --- a/src/finecode/workspace_manager/lsp_server/endpoints/action_tree.py +++ b/src/finecode/lsp_server/endpoints/action_tree.py @@ -1,15 +1,16 @@ import asyncio from pathlib import Path +import ordered_set from loguru import logger from pygls.lsp.server import LanguageServer -from finecode.workspace_manager import context, domain -from finecode.workspace_manager import services as wm_services -from finecode.workspace_manager import user_messages -from finecode.workspace_manager.lsp_server import global_state, schemas -from finecode.workspace_manager.lsp_server.services import ActionNotFound, InternalError -from finecode.workspace_manager.runner import runner_client +from finecode import context, domain +from finecode import services as wm_services +from finecode import user_messages +from finecode.lsp_server import global_state, schemas +from finecode.lsp_server.services import ActionNotFound, InternalError +from finecode.runner import runner_client async def list_actions(ls: LanguageServer, params): @@ -37,7 +38,7 @@ def get_project_action_tree( project: domain.Project, ws_context: context.WorkspaceContext ) -> list[schemas.ActionTreeNode]: actions_nodes: list[schemas.ActionTreeNode] = [] - if project.status == domain.ProjectStatus.RUNNING: + if project.status == domain.ProjectStatus.CONFIG_VALID: assert project.actions is not None for action in project.actions: node_id = f"{project.dir_path.as_posix()}::{action.name}" @@ -67,7 +68,7 @@ def get_project_action_tree( ) else: logger.info( - f"Project is not running: {project.dir_path}, no actions will be shown" + f"Project has no valid config and finecode: {project.dir_path}, no actions will be shown" ) return actions_nodes @@ -175,10 +176,11 @@ async def __list_actions( # list ws dirs and first level # wait for start of all runners, this is required to be able to resolve presets - all_started_coros = [ - runner.initialized_event.wait() - for runner in ws_context.ws_projects_extension_runners.values() - ] + all_started_coros = [] + for envs in ws_context.ws_projects_extension_runners.values(): + # all presets are expected to be in `dev_no_runtime` env + dev_no_runtime_runner = envs["dev_no_runtime"] + all_started_coros.append(dev_no_runtime_runner.initialized_event.wait()) await asyncio.gather(*all_started_coros) nodes: list[schemas.ActionTreeNode] = create_node_list_for_ws(ws_context) @@ -279,19 +281,28 @@ async def __reload_action(action_node_id: str) -> None: action_name = splitted_action_id[1] try: - next(action for action in project.actions if action.name == action_name) + action = next( + action for action in project.actions if action.name == action_name + ) except StopIteration as error: logger.error(f"Unexpected error, project or action not found: {error}") raise InternalError() - runner = global_state.ws_context.ws_projects_extension_runners[project_path] - - try: - await runner_client.reload_action(runner, action_name) - except runner_client.BaseRunnerRequestException as error: - await user_messages.error( - f"Action {action_name} reload failed: {error.message}" - ) + all_handlers_envs = ordered_set.OrderedSet( + [handler.env for handler in action.handlers] + ) + for env in all_handlers_envs: + # parallel to speed up? + runner = global_state.ws_context.ws_projects_extension_runners[project_path][ + env + ] + + try: + await runner_client.reload_action(runner, action_name) + except runner_client.BaseRunnerRequestException as error: + await user_messages.error( + f"Action {action_name} reload failed: {error.message}" + ) async def run_action( @@ -312,13 +323,19 @@ async def run_action( action_name = splitted_action_id[1] - response = await wm_services.run_action( - action_name=action_name, - params=request.params, - project_def=project_def, - ws_context=global_state.ws_context, - ) - return schemas.RunActionResponse(result=response.result) + try: + response = await wm_services.run_action( + action_name=action_name, + params=request.params, + project_def=project_def, + ws_context=global_state.ws_context, + ) + result = response.result + except wm_services.ActionRunFailed as exception: + logger.error(exception.message) + result = {} + + return schemas.RunActionResponse(result=result) async def notify_changed_action_node( diff --git a/src/finecode/workspace_manager/lsp_server/endpoints/code_actions.py b/src/finecode/lsp_server/endpoints/code_actions.py similarity index 96% rename from src/finecode/workspace_manager/lsp_server/endpoints/code_actions.py rename to src/finecode/lsp_server/endpoints/code_actions.py index 44845b3..afbd007 100644 --- a/src/finecode/workspace_manager/lsp_server/endpoints/code_actions.py +++ b/src/finecode/lsp_server/endpoints/code_actions.py @@ -7,7 +7,7 @@ from lsprotocol import types # from finecode import pygls_types_utils, lsp_types -# from finecode.workspace_manager.server import global_state, proxy_utils +# from finecode.server import global_state, proxy_utils if TYPE_CHECKING: from pygls.lsp.server import LanguageServer diff --git a/src/finecode/workspace_manager/lsp_server/endpoints/code_lens.py b/src/finecode/lsp_server/endpoints/code_lens.py similarity index 100% rename from src/finecode/workspace_manager/lsp_server/endpoints/code_lens.py rename to src/finecode/lsp_server/endpoints/code_lens.py diff --git a/src/finecode/workspace_manager/lsp_server/endpoints/diagnostics.py b/src/finecode/lsp_server/endpoints/diagnostics.py similarity index 93% rename from src/finecode/workspace_manager/lsp_server/endpoints/diagnostics.py rename to src/finecode/lsp_server/endpoints/diagnostics.py index 689b4c6..8005807 100644 --- a/src/finecode/workspace_manager/lsp_server/endpoints/diagnostics.py +++ b/src/finecode/lsp_server/endpoints/diagnostics.py @@ -9,17 +9,20 @@ from loguru import logger from lsprotocol import types -from finecode import pygls_types_utils -from finecode.workspace_manager import domain, project_analyzer, proxy_utils -from finecode.workspace_manager.lsp_server import global_state -from finecode.workspace_manager.runner import runner_client +from finecode import ( + context, + domain, + project_analyzer, + proxy_utils, + pygls_types_utils, + services, +) +from finecode.lsp_server import global_state from finecode_extension_api.actions import lint as lint_action if TYPE_CHECKING: from pygls.lsp.server import LanguageServer - from finecode.workspace_manager.runner import runner_info - def map_lint_message_to_diagnostic( lint_message: lint_action.LintMessage, @@ -223,7 +226,7 @@ async def document_diagnostic( @dataclass class LintActionExecInfo: - runner: runner_info.ExtensionRunnerInfo + project_dir_path: Path action_name: str request_data: dict[str, str | list[str]] = field(default_factory=dict) @@ -238,7 +241,8 @@ async def run_workspace_diagnostic_with_partial_results( action_name="lint", params=exec_info.request_data, partial_result_token=partial_result_token, - runner=exec_info.runner, + project_dir_path=exec_info.project_dir_path, + ws_context=global_state.ws_context, ) as response: async for partial_response in response: lint_subresult = lint_action.LintRunResult(**partial_response) @@ -283,16 +287,21 @@ async def workspace_diagnostic_with_partial_results( return types.WorkspaceDiagnosticReport(items=[]) -async def workspace_diagnostic_with_full_result(exec_infos: list[LintActionExecInfo]): +async def workspace_diagnostic_with_full_result( + exec_infos: list[LintActionExecInfo], ws_context: context.WorkspaceContext +): send_tasks: list[asyncio.Task] = [] try: async with asyncio.TaskGroup() as tg: for exec_info in exec_infos: + project = ws_context.ws_projects[exec_info.project_dir_path] task = tg.create_task( - runner_client.run_action( - runner=exec_info.runner, + services.run_action( action_name=exec_info.action_name, params=exec_info.request_data, + project_def=project, + ws_context=ws_context, + preprocess_payload=False, ) ) send_tasks.append(task) @@ -332,9 +341,9 @@ async def _workspace_diagnostic( exec_info_by_project_dir_path: dict[Path, LintActionExecInfo] = {} for project_dir_path in relevant_projects_paths: - runner = global_state.ws_context.ws_projects_extension_runners[project_dir_path] + project = global_state.ws_context.ws_projects[project_dir_path] exec_info_by_project_dir_path[project_dir_path] = LintActionExecInfo( - runner=runner, action_name="lint" + project_dir_path=project_dir_path, action_name="lint" ) # find which runner is responsible for which files @@ -351,9 +360,9 @@ async def _workspace_diagnostic( for project_dir_path, files_for_runner in files_by_projects.items(): project = global_state.ws_context.ws_projects[project_dir_path] - if project.status != domain.ProjectStatus.RUNNING: + if project.status != domain.ProjectStatus.CONFIG_VALID: logger.warning( - f"Runner of project {project_dir_path} is not running," + f"Project {project_dir_path} has not valid configuration and finecode," " lint in it will not be executed" ) continue @@ -373,7 +382,9 @@ async def _workspace_diagnostic( exec_infos=exec_infos, partial_result_token=params.partial_result_token ) else: - return await workspace_diagnostic_with_full_result(exec_infos=exec_infos) + return await workspace_diagnostic_with_full_result( + exec_infos=exec_infos, ws_context=global_state.ws_context + ) async def workspace_diagnostic( diff --git a/src/finecode/workspace_manager/lsp_server/endpoints/document_sync.py b/src/finecode/lsp_server/endpoints/document_sync.py similarity index 68% rename from src/finecode/workspace_manager/lsp_server/endpoints/document_sync.py rename to src/finecode/lsp_server/endpoints/document_sync.py index 3c58020..7cc47ff 100644 --- a/src/finecode/workspace_manager/lsp_server/endpoints/document_sync.py +++ b/src/finecode/lsp_server/endpoints/document_sync.py @@ -5,9 +5,9 @@ from lsprotocol import types from pygls.lsp.server import LanguageServer -from finecode.workspace_manager import domain -from finecode.workspace_manager.lsp_server import global_state -from finecode.workspace_manager.runner import runner_client +from finecode import domain +from finecode.lsp_server import global_state +from finecode.runner import runner_client, runner_info async def document_did_open( @@ -34,14 +34,15 @@ async def document_did_open( try: async with asyncio.TaskGroup() as tg: for project_path in projects_paths: - runner = global_state.ws_context.ws_projects_extension_runners[ + runners_by_env = global_state.ws_context.ws_projects_extension_runners[ project_path ] - tg.create_task( - runner_client.notify_document_did_open( - runner=runner, document_info=document_info + for runner in runners_by_env.values(): + tg.create_task( + runner_client.notify_document_did_open( + runner=runner, document_info=document_info + ) ) - ) except ExceptionGroup as e: logger.error(f"Error while sending opened document: {e}") @@ -62,21 +63,28 @@ async def document_did_close( projects_paths = [ project_path for project_path, project in global_state.ws_context.ws_projects.items() - if project.status == domain.ProjectStatus.RUNNING + if project.status == domain.ProjectStatus.CONFIG_VALID and file_path.is_relative_to(project_path) ] try: async with asyncio.TaskGroup() as tg: for project_path in projects_paths: - runner = global_state.ws_context.ws_projects_extension_runners[ + runners_by_env = global_state.ws_context.ws_projects_extension_runners[ project_path ] - tg.create_task( - runner_client.notify_document_did_close( - runner=runner, document_uri=params.text_document.uri + for runner in runners_by_env.values(): + if runner.status != runner_info.RunnerStatus.RUNNING: + logger.trace( + f"Runner {runner.working_dir_path} is not running, skip it" + ) + continue + + tg.create_task( + runner_client.notify_document_did_close( + runner=runner, document_uri=params.text_document.uri + ) ) - ) except ExceptionGroup as e: logger.error(f"Error while sending closed document: {e}") diff --git a/src/finecode/workspace_manager/lsp_server/endpoints/formatting.py b/src/finecode/lsp_server/endpoints/formatting.py similarity index 95% rename from src/finecode/workspace_manager/lsp_server/endpoints/formatting.py rename to src/finecode/lsp_server/endpoints/formatting.py index ce32c15..b6c2fee 100644 --- a/src/finecode/workspace_manager/lsp_server/endpoints/formatting.py +++ b/src/finecode/lsp_server/endpoints/formatting.py @@ -5,9 +5,8 @@ from loguru import logger from lsprotocol import types -from finecode import pygls_types_utils -from finecode.workspace_manager import proxy_utils -from finecode.workspace_manager.lsp_server import global_state +from finecode import proxy_utils, pygls_types_utils +from finecode.lsp_server import global_state if TYPE_CHECKING: from pygls.lsp.server import LanguageServer diff --git a/src/finecode/workspace_manager/lsp_server/endpoints/inlay_hints.py b/src/finecode/lsp_server/endpoints/inlay_hints.py similarity index 93% rename from src/finecode/workspace_manager/lsp_server/endpoints/inlay_hints.py rename to src/finecode/lsp_server/endpoints/inlay_hints.py index f994520..8fa3a95 100644 --- a/src/finecode/workspace_manager/lsp_server/endpoints/inlay_hints.py +++ b/src/finecode/lsp_server/endpoints/inlay_hints.py @@ -5,9 +5,8 @@ from loguru import logger from lsprotocol import types -from finecode import pygls_types_utils -from finecode.workspace_manager import find_project, proxy_utils -from finecode.workspace_manager.lsp_server import global_state +from finecode import find_project, proxy_utils, pygls_types_utils +from finecode.lsp_server import global_state if TYPE_CHECKING: from pygls.lsp.server import LanguageServer diff --git a/src/finecode/workspace_manager/lsp_server/global_state.py b/src/finecode/lsp_server/global_state.py similarity index 82% rename from src/finecode/workspace_manager/lsp_server/global_state.py rename to src/finecode/lsp_server/global_state.py index 4740e17..61df4ce 100644 --- a/src/finecode/workspace_manager/lsp_server/global_state.py +++ b/src/finecode/lsp_server/global_state.py @@ -2,7 +2,7 @@ import collections.abc from typing import Any -from finecode.workspace_manager import context +from finecode import context ws_context = context.WorkspaceContext([]) server_initialized = asyncio.Event() diff --git a/src/finecode/workspace_manager/lsp_server/lsp_server.py b/src/finecode/lsp_server/lsp_server.py similarity index 91% rename from src/finecode/workspace_manager/lsp_server/lsp_server.py rename to src/finecode/lsp_server/lsp_server.py index 8894727..751e255 100644 --- a/src/finecode/workspace_manager/lsp_server/lsp_server.py +++ b/src/finecode/lsp_server/lsp_server.py @@ -7,29 +7,15 @@ from lsprotocol import types from pygls.lsp.server import LanguageServer -from finecode.workspace_manager import services as wm_services -from finecode.workspace_manager.lsp_server import global_state, schemas, services -from finecode.workspace_manager.lsp_server.endpoints import ( - action_tree as action_tree_endpoints, -) -from finecode.workspace_manager.lsp_server.endpoints import ( - code_actions as code_actions_endpoints, -) -from finecode.workspace_manager.lsp_server.endpoints import ( - code_lens as code_lens_endpoints, -) -from finecode.workspace_manager.lsp_server.endpoints import ( - diagnostics as diagnostics_endpoints, -) -from finecode.workspace_manager.lsp_server.endpoints import ( - document_sync as document_sync_endpoints, -) -from finecode.workspace_manager.lsp_server.endpoints import ( - formatting as formatting_endpoints, -) -from finecode.workspace_manager.lsp_server.endpoints import ( - inlay_hints as inlay_hints_endpoints, -) +from finecode import services as wm_services +from finecode.lsp_server import global_state, schemas, services +from finecode.lsp_server.endpoints import action_tree as action_tree_endpoints +from finecode.lsp_server.endpoints import code_actions as code_actions_endpoints +from finecode.lsp_server.endpoints import code_lens as code_lens_endpoints +from finecode.lsp_server.endpoints import diagnostics as diagnostics_endpoints +from finecode.lsp_server.endpoints import document_sync as document_sync_endpoints +from finecode.lsp_server.endpoints import formatting as formatting_endpoints +from finecode.lsp_server.endpoints import inlay_hints as inlay_hints_endpoints def create_lsp_server() -> LanguageServer: @@ -263,14 +249,14 @@ async def reset(ls: LanguageServer, params): async def restart_extension_runner(ls: LanguageServer, params): - logger.info(f"restart extension runner {params}") + logger.info(f"restart extension runners {params}") await global_state.server_initialized.wait() params_dict = params[0] runner_working_dir_str = params_dict["projectPath"] runner_working_dir_path = Path(runner_working_dir_str) - await wm_services.restart_extension_runner( + await wm_services.restart_extension_runners( runner_working_dir_path, global_state.ws_context ) diff --git a/src/finecode/workspace_manager/lsp_server/schemas.py b/src/finecode/lsp_server/schemas.py similarity index 100% rename from src/finecode/workspace_manager/lsp_server/schemas.py rename to src/finecode/lsp_server/schemas.py diff --git a/src/finecode/workspace_manager/lsp_server/services.py b/src/finecode/lsp_server/services.py similarity index 92% rename from src/finecode/workspace_manager/lsp_server/services.py rename to src/finecode/lsp_server/services.py index e1ec5ed..26a7c85 100644 --- a/src/finecode/workspace_manager/lsp_server/services.py +++ b/src/finecode/lsp_server/services.py @@ -2,10 +2,10 @@ from loguru import logger -from finecode.workspace_manager import domain, user_messages -from finecode.workspace_manager.config import read_configs -from finecode.workspace_manager.lsp_server import global_state, schemas -from finecode.workspace_manager.runner import manager as runner_manager +from finecode import domain, user_messages +from finecode.config import read_configs +from finecode.lsp_server import global_state, schemas +from finecode.runner import manager as runner_manager class ActionNotFound(Exception): ... diff --git a/src/finecode/workspace_manager/main.py b/src/finecode/main.py similarity index 92% rename from src/finecode/workspace_manager/main.py rename to src/finecode/main.py index 827453c..6752726 100644 --- a/src/finecode/workspace_manager/main.py +++ b/src/finecode/main.py @@ -1,8 +1,8 @@ from __future__ import annotations from finecode import communication_utils # pygls_server_utils -from finecode.workspace_manager import logger_utils -from finecode.workspace_manager.lsp_server.lsp_server import create_lsp_server +from finecode import logger_utils +from finecode.lsp_server.lsp_server import create_lsp_server # async def start( # comm_type: communication_utils.CommunicationType, diff --git a/src/finecode/payload_preprocessor.py b/src/finecode/payload_preprocessor.py new file mode 100644 index 0000000..a786a62 --- /dev/null +++ b/src/finecode/payload_preprocessor.py @@ -0,0 +1,60 @@ +import pathlib +import typing + +from finecode import context, project_analyzer + + +def preprocess_for_project( + action_name: str, + payload: dict[str, typing.Any], + project_dir_path: pathlib.Path, + ws_context: context.WorkspaceContext, +) -> dict[str, typing.Any]: + processed_payload = payload.copy() + + # temporary hardcore logic until we get the proper payload structure and defaults + # from extension runner + if action_name == "lint" or action_name == "format": + if "file_paths" not in processed_payload: + processed_payload["file_paths"] = None + + if action_name == "format" and "save" not in processed_payload: + processed_payload["save"] = True + elif action_name == "prepare_envs" or action_name == "prepare_runners": + runtime_venv_path = project_dir_path / ".venvs" / "runtime" + project_def_path = project_dir_path / "pyproject.toml" + envs = [ + { + "name": "runtime", + "venv_dir_path": runtime_venv_path, + "project_def_path": project_def_path, + } + ] + # current approach: there are 4 default environments: runtime, dev_workspace, + # dev, dev_no_runtime. `runtime` is created always, all other only if dependency + # group for them exist. + # In future there will be possibility to create additional envs and to configure + # default ones. + project_raw_config = ws_context.ws_projects_raw_configs[project_dir_path] + deps_groups = project_raw_config.get("dependency-groups", {}) + # `dev_workspace` is handled separately in `prepare_env`, no need to include + # here + for default_env in ["dev", "dev_no_runtime"]: + if default_env in deps_groups: + venv_path = project_dir_path / ".venvs" / default_env + envs.append( + { + "name": default_env, + "venv_dir_path": venv_path, + "project_def_path": project_def_path, + } + ) + processed_payload["envs"] = envs + + for param, value in processed_payload.items(): + if param == "file_paths" and value is None: + processed_payload["file_paths"] = project_analyzer.get_project_files( + project_dir_path + ) + + return processed_payload diff --git a/src/finecode/workspace_manager/project_analyzer.py b/src/finecode/project_analyzer.py similarity index 81% rename from src/finecode/workspace_manager/project_analyzer.py rename to src/finecode/project_analyzer.py index aad5d4a..5718062 100644 --- a/src/finecode/workspace_manager/project_analyzer.py +++ b/src/finecode/project_analyzer.py @@ -7,9 +7,11 @@ def get_files_by_projects(projects_dirs_paths: list[Path]) -> dict[Path, list[Pa if len(projects_dirs_paths) == 1: project_dir = projects_dirs_paths[0] files_by_projects_dirs[project_dir] = [ - path for path in project_dir.rglob("*.py") + path + for path in project_dir.rglob("*.py") # TODO: make configurable? - if '__testdata__' not in path.relative_to(project_dir).parts and '.venvs' not in path.relative_to(project_dir).parts + if "__testdata__" not in path.relative_to(project_dir).parts + and ".venvs" not in path.relative_to(project_dir).parts ] else: # copy to avoid modifying of argument values @@ -55,9 +57,11 @@ def get_files_by_projects(projects_dirs_paths: list[Path]) -> dict[Path, list[Pa if len(dir_items_with_children) == 0: # if there are no children with subprojects, we can just rglob files_by_projects_dirs[project_dir_path].extend( - path for path in project_dir_path.rglob("*.py") + path + for path in project_dir_path.rglob("*.py") # TODO: make configurable? - if '__testdata__' not in path.relative_to(project_dir_path).parts and '.venvs' not in path.relative_to(project_dir_path).parts + if "__testdata__" not in path.relative_to(project_dir_path).parts + and ".venvs" not in path.relative_to(project_dir_path).parts ) else: # process all dir items which don't have child projects @@ -69,9 +73,13 @@ def get_files_by_projects(projects_dirs_paths: list[Path]) -> dict[Path, list[Pa files_by_projects_dirs[project_dir_path].append(dir_item) elif dir_item.is_dir(): files_by_projects_dirs[project_dir_path].extend( - path for path in dir_item.rglob("*.py") + path + for path in dir_item.rglob("*.py") # TODO: make configurable? - if '__testdata__' not in path.relative_to(project_dir_path).parts and '.venvs' not in path.relative_to(project_dir_path).parts + if "__testdata__" + not in path.relative_to(project_dir_path).parts + and ".venvs" + not in path.relative_to(project_dir_path).parts ) # process all dir items which have child projects @@ -108,9 +116,13 @@ def get_files_by_projects(projects_dirs_paths: list[Path]) -> dict[Path, list[Pa else: # subdirectory without child projects, rglob it files_by_projects_dirs[project_dir_path].extend( - path for path in dir_item.rglob("*.py") + path + for path in dir_item.rglob("*.py") # TODO: make configurable? - if '__testdata__' not in path.relative_to(project_dir_path).parts and '.venvs' not in path.relative_to(project_dir_path).parts + if "__testdata__" + not in path.relative_to(project_dir_path).parts + and ".venvs" + not in path.relative_to(project_dir_path).parts ) return files_by_projects_dirs diff --git a/src/finecode/workspace_manager/proxy_utils.py b/src/finecode/proxy_utils.py similarity index 52% rename from src/finecode/workspace_manager/proxy_utils.py rename to src/finecode/proxy_utils.py index ca0c206..eedf32f 100644 --- a/src/finecode/workspace_manager/proxy_utils.py +++ b/src/finecode/proxy_utils.py @@ -1,22 +1,22 @@ import asyncio import collections.abc import contextlib -from pathlib import Path +import pathlib from typing import Any +import ordered_set from loguru import logger -from finecode.workspace_manager import context, domain, find_project -from finecode.workspace_manager.runner import manager as runner_manager -from finecode.workspace_manager.runner import runner_client, runner_info +from finecode import context, domain, find_project, services +from finecode.runner import manager as runner_manager +from finecode.runner import runner_client, runner_info +from finecode.runner.manager import RunnerFailedToStart +from finecode.services import ActionRunFailed -class ActionRunFailed(Exception): ... - - -def find_action_project_runner( - file_path: Path, action_name: str, ws_context: context.WorkspaceContext -) -> runner_info.ExtensionRunnerInfo: +def find_action_project( + file_path: pathlib.Path, action_name: str, ws_context: context.WorkspaceContext +) -> pathlib.Path: try: project_path = find_project.find_project_with_action_for_file( file_path=file_path, @@ -32,36 +32,40 @@ def find_action_project_runner( raise ActionRunFailed(error) project_status = ws_context.ws_projects[project_path].status - if project_status != domain.ProjectStatus.RUNNING: + if project_status != domain.ProjectStatus.CONFIG_VALID: logger.info( - f"Extension runner {project_path} is not running, " + f"Extension runner {project_path} has no valid config with finecode, " f"status: {project_status.name}" ) raise ActionRunFailed( - f"Extension runner {project_path} is not running, " + f"Project {project_path} has no valid config with finecode," f"status: {project_status.name}" ) - runner = ws_context.ws_projects_extension_runners[project_path] - return runner + return project_path async def find_action_project_and_run( - file_path: Path, + file_path: pathlib.Path, action_name: str, params: dict[str, Any], ws_context: context.WorkspaceContext, ) -> runner_client.RunActionResponse: - runner = find_action_project_runner( + project_path = find_action_project( file_path=file_path, action_name=action_name, ws_context=ws_context ) + project = ws_context.ws_projects[project_path] + try: - response = await runner_client.run_action( - runner=runner, action_name=action_name, params=params + response = await services.run_action( + action_name=action_name, + params=params, + project_def=project, + ws_context=ws_context, + preprocess_payload=False, ) - except runner_client.BaseRunnerRequestException as error: - logger.error(f"Error on running action {action_name} on {file_path}: {error.message}") - raise ActionRunFailed(error.message) + except services.ActionRunFailed as exception: + raise exception return response @@ -133,7 +137,7 @@ async def run_action_and_notify( runner: runner_info.ExtensionRunnerInfo, result_list: AsyncList, partial_results_task: asyncio.Task, -) -> None: +) -> runner_client.RunActionResponse: try: return await run_action_in_runner( action_name=action_name, @@ -163,11 +167,12 @@ async def run_with_partial_results( action_name: str, params: dict[str, Any], partial_result_token: int | str, - runner: runner_info.ExtensionRunnerInfo, + project_dir_path: pathlib.Path, + ws_context: context.WorkspaceContext, ) -> collections.abc.AsyncIterator[ collections.abc.AsyncIterable[domain.PartialResultRawValue] ]: - logger.trace(f"Run {action_name} in runner {runner.working_dir_path}") + logger.trace(f"Run {action_name} in project {project_dir_path}") result: AsyncList[domain.PartialResultRawValue] = AsyncList() try: @@ -177,16 +182,24 @@ async def run_with_partial_results( result_list=result, partial_result_token=partial_result_token ) ) - tg.create_task( - run_action_and_notify( - action_name=action_name, - params=params, - partial_result_token=partial_result_token, - runner=runner, - result_list=result, - partial_results_task=partial_results_task, - ) + project = ws_context.ws_projects[project_dir_path] + action = next(action for action in project.actions if action.name == "lint") + action_envs = ordered_set.OrderedSet( + [handler.env for handler in action.handlers] ) + runners_by_env = ws_context.ws_projects_extension_runners[project_dir_path] + for env in action_envs: + runner = runners_by_env[env] + tg.create_task( + run_action_and_notify( + action_name=action_name, + params=params, + partial_result_token=partial_result_token, + runner=runner, + result_list=result, + partial_results_task=partial_results_task, + ) + ) yield result except ExceptionGroup as eg: @@ -197,39 +210,39 @@ async def run_with_partial_results( @contextlib.asynccontextmanager async def find_action_project_and_run_with_partial_results( - file_path: Path, + file_path: pathlib.Path, action_name: str, params: dict[str, Any], partial_result_token: int | str, ws_context: context.WorkspaceContext, ) -> collections.abc.AsyncIterator[runner_client.RunActionRawResult]: logger.trace(f"Run {action_name} on {file_path}") - runner = find_action_project_runner( + project_path = find_action_project( file_path=file_path, action_name=action_name, ws_context=ws_context ) - return run_with_partial_results( action_name=action_name, params=params, partial_result_token=partial_result_token, - runner=runner, + project_dir_path=project_path, + ws_context=ws_context, ) def find_all_projects_with_action( action_name: str, ws_context: context.WorkspaceContext -) -> list[Path]: +) -> list[pathlib.Path]: projects = ws_context.ws_projects - relevant_projects: dict[Path, domain.Project] = { + relevant_projects: dict[pathlib.Path, domain.Project] = { path: project for path, project in projects.items() if project.status != domain.ProjectStatus.NO_FINECODE } - # exclude not running projects and projects without requested action + # exclude projects without valid config and projects without requested action for project_dir_path, project_def in relevant_projects.copy().items(): - if project_def.status != domain.ProjectStatus.RUNNING: - # projects that are not running, have no actions. Files of those projects + if project_def.status != domain.ProjectStatus.CONFIG_VALID: + # projects without valid config have no actions. Files of those projects # will be not processed because we don't know whether it has one of expected # actions continue @@ -243,12 +256,85 @@ def find_all_projects_with_action( del relevant_projects[project_dir_path] continue - relevant_projects_paths: list[Path] = list(relevant_projects.keys()) + relevant_projects_paths: list[pathlib.Path] = list(relevant_projects.keys()) return relevant_projects_paths +class StartingEnvironmentsFailed(Exception): + def __init__(self, message: str) -> None: + self.message = message + + +async def start_required_environments( + actions_by_projects: dict[pathlib.Path, list[str]], + ws_context: context.WorkspaceContext, + update_config_in_running_runners: bool = False, +) -> None: + """Collect all required envs from actions that will be run and start them.""" + required_envs_by_project: dict[pathlib.Path, set[str]] = {} + for project_dir_path, action_names in actions_by_projects.items(): + project = ws_context.ws_projects[project_dir_path] + if project.actions is not None: + project_required_envs = set() + for action_name in action_names: + # find the action and collect envs from its handlers + action = next( + (a for a in project.actions if a.name == action_name), None + ) + if action is not None: + for handler in action.handlers: + project_required_envs.add(handler.env) + required_envs_by_project[project_dir_path] = project_required_envs + + # start runners for required environments that aren't already running + for project_dir_path, required_envs in required_envs_by_project.items(): + project = ws_context.ws_projects[project_dir_path] + existing_runners = ws_context.ws_projects_extension_runners.get( + project_dir_path, {} + ) + + for env_name in required_envs: + runner_exist = env_name in existing_runners + start_runner = True + if runner_exist: + runner_is_running = ( + existing_runners[env_name].status + == runner_info.RunnerStatus.RUNNING + ) + start_runner = not runner_is_running + + if start_runner: + try: + runner = await runner_manager.start_runner( + project_def=project, env_name=env_name, ws_context=ws_context + ) + except runner_manager.RunnerFailedToStart as e: + raise StartingEnvironmentsFailed( + f"Failed to start runner for env '{env_name}' in project '{project.name}': {e}" + ) + else: + if update_config_in_running_runners: + runner = existing_runners[env_name] + logger.trace( + f"Runner {runner.working_dir_path} {runner.env_name} is running already, update config" + ) + + try: + await runner_manager.update_runner_config( + runner=runner, project=project + ) + except RunnerFailedToStart as exception: + raise StartingEnvironmentsFailed( + f"Failed to update config of runner {runner.working_dir_path} {runner.env_name}" + ) + + __all__ = [ "find_action_project_and_run", "find_action_project_and_run_with_partial_results", "run_with_partial_results", + # reexport for easier use of proxy helpers + "ActionRunFailed", + "start_required_environments", + "StartingEnvironmentsFailed", ] diff --git a/src/finecode/runner/__init__.py b/src/finecode/runner/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/finecode/runner/manager.py b/src/finecode/runner/manager.py new file mode 100644 index 0000000..a6c5903 --- /dev/null +++ b/src/finecode/runner/manager.py @@ -0,0 +1,559 @@ +import asyncio +import json +import os +import shutil +from pathlib import Path +from typing import Callable, Coroutine + +from loguru import logger +from lsprotocol import types + +from finecode import context, dirs_utils, domain, finecode_cmd +from finecode.config import collect_actions, config_models, read_configs +from finecode.pygls_client_utils import create_lsp_client_io +from finecode.runner import runner_client, runner_info +from finecode.utils import iterable_subscribe + +project_changed_callback: ( + Callable[[domain.Project], Coroutine[None, None, None]] | None +) = None +get_document: Callable[[], Coroutine] | None = None +apply_workspace_edit: Callable[[], Coroutine] | None = None +partial_results: iterable_subscribe.IterableSubscribe = ( + iterable_subscribe.IterableSubscribe() +) + + +class RunnerFailedToStart(Exception): + def __init__(self, message: str) -> None: + self.message = message + + +async def notify_project_changed(project: domain.Project) -> None: + if project_changed_callback is not None: + await project_changed_callback(project) + + +async def _apply_workspace_edit(params: types.ApplyWorkspaceEditParams): + def map_change_object(change): + return types.TextEdit( + range=types.Range( + start=types.Position( + line=change.range.start.line, character=change.range.start.character + ), + end=types.Position( + change.range.end.line, character=change.range.end.character + ), + ), + new_text=change.newText, + ) + + converted_params = types.ApplyWorkspaceEditParams( + edit=types.WorkspaceEdit( + document_changes=[ + types.TextDocumentEdit( + text_document=types.OptionalVersionedTextDocumentIdentifier( + document_edit.textDocument.uri + ), + edits=[map_change_object(change) for change in document_edit.edits], + ) + for document_edit in params.edit.documentChanges + ] + ) + ) + return await apply_workspace_edit(converted_params) + + +async def start_extension_runner( + runner_dir: Path, env_name: str, ws_context: context.WorkspaceContext +) -> runner_info.ExtensionRunnerInfo | None: + runner_info_instance = runner_info.ExtensionRunnerInfo( + working_dir_path=runner_dir, + env_name=env_name, + status=runner_info.RunnerStatus.READY_TO_START, + initialized_event=asyncio.Event(), + client=None, + ) + + try: + python_cmd = finecode_cmd.get_python_cmd(runner_dir, env_name) + except ValueError: + try: + runner_info_instance.status = runner_info.RunnerStatus.NO_VENV + await notify_project_changed(ws_context.ws_projects[runner_dir]) + except KeyError: + ... + logger.error( + f"Project {runner_dir} uses finecode, but env (venv) doesn't exist yet. Run `prepare_env` command to create it" + ) + return None + + process_args: list[str] = [ + "--trace", + f"--project-path={runner_dir.as_posix()}", + f"--env-name={env_name}", + ] + env_config = ws_context.ws_projects[runner_dir].env_configs[env_name] + runner_config = env_config.runner_config + # TODO: also check whether lsp server is available, without it doesn't make sense + # to start with debugger + if runner_config.debug: + process_args.append("--debug") + # TODO: find free port and pass it + process_args.append("--debug-port=5681") + + process_args_str: str = " ".join(process_args) + client = await create_lsp_client_io( + runner_info.CustomJsonRpcClient, + f"{python_cmd} -m finecode_extension_runner.cli start {process_args_str}", + runner_dir, + ) + runner_info_instance.client = client + # TODO: recognize started debugger and send command to lsp server + + async def on_exit(): + logger.debug(f"Extension Runner {runner_info_instance.working_dir_path} exited") + runner_info_instance.status = runner_info.RunnerStatus.EXITED + await notify_project_changed(ws_context.ws_projects[runner_dir]) # TODO: fix + # TODO: restart if WM is not stopping + + runner_info_instance.client.server_exit_callback = on_exit + + if get_document is not None: + register_get_document_feature = runner_info_instance.client.feature( + "documents/get" + ) + register_get_document_feature(get_document) + + register_workspace_apply_edit = runner_info_instance.client.feature( + types.WORKSPACE_APPLY_EDIT + ) + register_workspace_apply_edit(_apply_workspace_edit) + + async def on_progress(params: types.ProgressParams): + logger.debug(f"Got progress from runner for token: {params.token}") + partial_result = domain.PartialResult( + token=params.token, value=json.loads(params.value) + ) + partial_results.publish(partial_result) + + register_progress_feature = runner_info_instance.client.feature(types.PROGRESS) + register_progress_feature(on_progress) + + async def get_project_raw_config(params): + project_def_path_str = params.projectDefPath + project_def_path = Path(project_def_path_str) + try: + project_raw_config = ws_context.ws_projects_raw_configs[ + project_def_path.parent + ] + except KeyError: + raise ValueError(f"Config of project '{project_def_path_str}' not found") + return {"config": json.dumps(project_raw_config)} + + register_get_project_raw_config_feature = runner_info_instance.client.feature( + "projects/getRawConfig" + ) + register_get_project_raw_config_feature(get_project_raw_config) + + return runner_info_instance + + +async def stop_extension_runner(runner: runner_info.ExtensionRunnerInfo) -> None: + logger.trace(f"Trying to stop extension runner {runner.working_dir_path}") + if not runner.client.stopped: + logger.debug("Send shutdown to server") + try: + await runner_client.shutdown(runner=runner) + except Exception as e: + logger.error(f"Failed to shutdown: {e}") + + await runner_client.exit(runner) + logger.debug("Sent exit to server") + await runner.client.stop() + logger.trace( + f"Stop extension runner {runner.process_id}" + f" in {runner.working_dir_path}" + ) + else: + logger.trace("Extension runner was not running") + + +def stop_extension_runner_sync(runner: runner_info.ExtensionRunnerInfo) -> None: + logger.trace(f"Trying to stop extension runner {runner.working_dir_path}") + if not runner.client.stopped: + logger.debug("Send shutdown to server") + try: + runner_client.shutdown_sync(runner=runner) + except Exception as e: + # currently we get (almost?) always this error. TODO: Investigate why + # mute for now to make output less verbose + # logger.error(f"Failed to shutdown: {e}") + ... + + runner_client.exit_sync(runner) + logger.debug("Sent exit to server") + logger.trace( + f"Stop extension runner {runner.process_id}" + f" in {runner.working_dir_path}" + ) + else: + logger.trace("Extension runner was not running") + + +async def kill_extension_runner(runner: runner_info.ExtensionRunnerInfo) -> None: + if runner.client is not None: + if runner.client._server is not None: + runner.client._server.terminate() + await runner.client.stop() + + +async def update_runners(ws_context: context.WorkspaceContext) -> None: + # starts runners for new(=which don't have runner yet) projects in `ws_context` + # and stops runners for projects which are not in `ws_context` anymore + # + # during initialization of new runners it also reads their configurations and + # actions + # + # this function should handle all possible statuses of projects and they either + # start of fail to start, only projects without finecode are ignored + extension_runners_paths = list(ws_context.ws_projects_extension_runners.keys()) + new_dirs, deleted_dirs = dirs_utils.find_changed_dirs( + [*ws_context.ws_projects.keys()], + extension_runners_paths, + ) + for deleted_dir in deleted_dirs: + runners_by_env = ws_context.ws_projects_extension_runners[deleted_dir] + for runner in runners_by_env.values(): + await stop_extension_runner(runner) + del ws_context.ws_projects_extension_runners[deleted_dir] + + projects = [ws_context.ws_projects[new_dir] for new_dir in new_dirs] + # first start runners with presets to be able to resolve presets + await start_runners_with_presets(projects, ws_context) + + new_runners_tasks: list[asyncio.Task] = [] + try: + # only then start runners for all other envs + new_runners_tasks = [] + async with asyncio.TaskGroup() as tg: + for new_dir in new_dirs: + project = ws_context.ws_projects[new_dir] + project_status = project.status + if ( + ws_context.ws_projects_extension_runners.get(new_dir, {}).get( + "dev_no_runtime", None + ) + is not None + ): + # start only if dev_no_runtime started successfully + for env in project.envs: + if env == "dev_no_runtime": + # this env has already started above + continue + + runner_task = tg.create_task( + start_extension_runner( + runner_dir=new_dir, env_name=env, ws_context=ws_context + ) + ) + new_runners_tasks.append(runner_task) + + except ExceptionGroup as eg: + for exception in eg.exceptions: + if isinstance( + exception, runner_client.BaseRunnerRequestException + ) or isinstance(exception, RunnerFailedToStart): + logger.error(exception.message) + else: + logger.error("Unexpected exception:") + logger.exception(exception) + raise RunnerFailedToStart("Failed to start runner") + + save_runners_from_tasks_in_context(tasks=new_runners_tasks, ws_context=ws_context) + extension_runners: list[runner_info.ExtensionRunnerInfo] = [ + runner.result() for runner in new_runners_tasks if runner is not None + ] + + try: + async with asyncio.TaskGroup() as tg: + for runner in extension_runners: + tg.create_task( + _init_runner( + runner, + ws_context.ws_projects[runner.working_dir_path], + ws_context, + ) + ) + except ExceptionGroup as eg: + for exception in eg.exceptions: + if isinstance(exception, runner_client.BaseRunnerRequestException): + logger.error(exception.message) + else: + logger.error("Unexpected exception:") + logger.exception(exception) + raise RunnerFailedToStart("Failed to initialize runner") + + +async def start_runners_with_presets( + projects: list[domain.Project], ws_context: context.WorkspaceContext +) -> None: + new_runners_tasks: list[asyncio.Task] = [] + try: + # first start runner in 'dev_no_runtime' env to be able to resolve presets for + # other envs (presets can be currently only in `dev_no_runtime` env) + async with asyncio.TaskGroup() as tg: + for project in projects: + project_status = project.status + if project_status == domain.ProjectStatus.CONFIG_VALID: + task = tg.create_task( + _start_dev_no_runtime_runner( + project_def=project, ws_context=ws_context + ) + ) + new_runners_tasks.append(task) + elif project_status != domain.ProjectStatus.NO_FINECODE: + raise RunnerFailedToStart( + f"Project '{project.name}' has invalid configuration, status: {project_status.name}" + ) + + save_runners_from_tasks_in_context( + tasks=new_runners_tasks, ws_context=ws_context + ) + except ExceptionGroup as eg: + for exception in eg.exceptions: + if isinstance( + exception, runner_client.BaseRunnerRequestException + ) or isinstance(exception, RunnerFailedToStart): + logger.error(exception.message) + else: + logger.error("Unexpected exception:") + logger.exception(exception) + raise RunnerFailedToStart( + "Failed to initialize runner(s). See previous logs for more details" + ) + + +async def start_runner( + project_def: domain.Project, env_name: str, ws_context: context.WorkspaceContext +) -> runner_info.ExtensionRunnerInfo: + runner = await start_extension_runner( + runner_dir=project_def.dir_path, env_name=env_name, ws_context=ws_context + ) + + if runner is None: + raise RunnerFailedToStart( + f"Runner '{env_name}' in project {project_def.name} failed to start" + ) + + save_runner_in_context(runner=runner, ws_context=ws_context) + + # we cannot reuse '_init_runner' here because we need to start lsp client first, + # read config(=also resolve presets) and only then we can update runner config, + # because this requires resolved project config with presets + await _init_lsp_client(runner=runner, project=project_def) + + if ( + project_def.dir_path not in ws_context.ws_projects_raw_configs + or project_def.actions is None + ): + try: + await read_configs.read_project_config( + project=project_def, ws_context=ws_context + ) + collect_actions.collect_actions( + project_path=project_def.dir_path, ws_context=ws_context + ) + except config_models.ConfigurationError as exception: + raise RunnerFailedToStart( + f"Found problem in configuration of {project_def.dir_path}: {exception.message}" + ) + + await update_runner_config(runner=runner, project=project_def) + await _finish_runner_init(runner=runner, project=project_def, ws_context=ws_context) + + return runner + + +async def _start_dev_no_runtime_runner( + project_def: domain.Project, ws_context: context.WorkspaceContext +) -> runner_info.ExtensionRunnerInfo: + return await start_runner( + project_def=project_def, env_name="dev_no_runtime", ws_context=ws_context + ) + + +async def _init_runner( + runner: runner_info.ExtensionRunnerInfo, + project: domain.Project, + ws_context: context.WorkspaceContext, +) -> None: + # initialization is required to be able to perform other requests + logger.trace(f"Init runner {runner.working_dir_path}") + assert project.actions is not None + + await _init_lsp_client(runner=runner, project=project) + + await update_runner_config(runner=runner, project=project) + await _finish_runner_init(runner=runner, project=project, ws_context=ws_context) + + +async def _init_lsp_client( + runner: runner_info.ExtensionRunnerInfo, project: domain.Project +) -> None: + try: + await runner_client.initialize( + runner, + client_process_id=os.getpid(), + client_name="FineCode_WorkspaceManager", + client_version="0.1.0", + ) + except runner_client.BaseRunnerRequestException as error: + runner.status = runner_info.RunnerStatus.FAILED + await notify_project_changed(project) + runner.initialized_event.set() + raise RunnerFailedToStart(f"Runner failed to initialize: {error.message}") + + try: + await runner_client.notify_initialized(runner) + except Exception as error: + logger.error(f"Failed to notify runner about initialization: {error}") + runner.status = runner_info.RunnerStatus.FAILED + await notify_project_changed(project) + runner.initialized_event.set() + logger.exception(error) + raise RunnerFailedToStart( + f"Runner failed to notify about initialization: {error}" + ) + + logger.debug("LSP Client initialized") + + +async def update_runner_config( + runner: runner_info.ExtensionRunnerInfo, project: domain.Project +) -> None: + assert project.actions is not None + config = runner_client.RunnerConfig( + actions=project.actions, action_handler_configs=project.action_handler_configs + ) + try: + await runner_client.update_config(runner, config) + except runner_client.BaseRunnerRequestException as exception: + runner.status = runner_info.RunnerStatus.FAILED + await notify_project_changed(project) + runner.initialized_event.set() + raise RunnerFailedToStart( + f"Runner failed to update config: {exception.message}" + ) + + logger.debug( + f"Updated config of runner {runner.working_dir_path}," + f" process id {runner.process_id}" + ) + + +async def _finish_runner_init( + runner: runner_info.ExtensionRunnerInfo, + project: domain.Project, + ws_context: context.WorkspaceContext, +) -> None: + runner.status = runner_info.RunnerStatus.RUNNING + await notify_project_changed(project) + + await send_opened_files( + runner=runner, opened_files=list(ws_context.opened_documents.values()) + ) + + runner.initialized_event.set() + + +def save_runners_from_tasks_in_context( + tasks: list[asyncio.Task], ws_context: context.WorkspaceContext +) -> None: + extension_runners: list[runner_info.ExtensionRunnerInfo] = [ + runner.result() for runner in tasks if runner is not None + ] + + for new_runner in extension_runners: + save_runner_in_context(runner=new_runner, ws_context=ws_context) + + +def save_runner_in_context( + runner: runner_info.ExtensionRunnerInfo, ws_context: context.WorkspaceContext +) -> None: + if runner.working_dir_path not in ws_context.ws_projects_extension_runners: + ws_context.ws_projects_extension_runners[runner.working_dir_path] = {} + ws_context.ws_projects_extension_runners[runner.working_dir_path][ + runner.env_name + ] = runner + + +async def send_opened_files( + runner: runner_info.ExtensionRunnerInfo, opened_files: list[domain.TextDocumentInfo] +): + files_for_runner: list[domain.TextDocumentInfo] = [] + for opened_file_info in opened_files: + file_path = Path(opened_file_info.uri.replace("file://", "")) + if not file_path.is_relative_to(runner.working_dir_path): + continue + else: + files_for_runner.append(opened_file_info) + + try: + async with asyncio.TaskGroup() as tg: + for file_info in files_for_runner: + tg.create_task( + runner_client.notify_document_did_open( + runner=runner, + document_info=domain.TextDocumentInfo( + uri=file_info.uri, version=file_info.version + ), + ) + ) + except ExceptionGroup as eg: + logger.error(f"Error while sending opened document: {eg.exceptions}") + + +async def check_runner(runner_dir: Path, env_name: str) -> bool: + try: + python_cmd = finecode_cmd.get_python_cmd(runner_dir, env_name) + except ValueError: + logger.debug(f"No venv for {env_name} of {runner_dir}") + # no venv + return False + + # get version of extension runner. If it works and we get valid + # value, assume extension runner works correctly + cmd = f"{python_cmd} -m finecode_extension_runner.cli version" + logger.debug(f"Run '{cmd}' in {runner_dir}") + async_subprocess = await asyncio.create_subprocess_shell( + cmd, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + cwd=runner_dir, + ) + try: + raw_stdout, raw_stderr = await asyncio.wait_for( + async_subprocess.communicate(), timeout=5 + ) + except asyncio.TimeoutError: + logger.debug(f"Timeout 5 sec({runner_dir})") + return False + + if async_subprocess.returncode != 0: + logger.debug( + f"Return code: {async_subprocess.returncode}, stderr: {raw_stderr.decode()}" + ) + return False + + stdout = raw_stdout.decode() + return "FineCode Extension Runner " in stdout + + +def remove_runner_venv(runner_dir: Path, env_name: str) -> None: + venv_dir_path = finecode_cmd.get_venv_dir_path( + project_path=runner_dir, env_name=env_name + ) + if venv_dir_path.exists(): + logger.debug(f"Remove venv {venv_dir_path}") + shutil.rmtree(venv_dir_path) diff --git a/src/finecode/workspace_manager/runner/runner_client.py b/src/finecode/runner/runner_client.py similarity index 85% rename from src/finecode/workspace_manager/runner/runner_client.py rename to src/finecode/runner/runner_client.py index 4942e3a..52c5ef9 100644 --- a/src/finecode/workspace_manager/runner/runner_client.py +++ b/src/finecode/runner/runner_client.py @@ -5,6 +5,7 @@ import asyncio import asyncio.subprocess +import dataclasses import enum import json import typing @@ -14,10 +15,10 @@ from lsprotocol import types from pygls import exceptions as pygls_exceptions -import finecode.workspace_manager.domain as domain +import finecode.domain as domain if TYPE_CHECKING: - from finecode.workspace_manager.runner.runner_info import ExtensionRunnerInfo + from finecode.runner.runner_info import ExtensionRunnerInfo class BaseRunnerRequestException(Exception): @@ -31,6 +32,12 @@ class NoResponse(BaseRunnerRequestException): ... class ResponseTimeout(BaseRunnerRequestException): ... +class ActionRunFailed(BaseRunnerRequestException): ... + + +class ActionRunStopped(BaseRunnerRequestException): ... + + async def log_process_log_streams(process: asyncio.subprocess.Process) -> None: stdout, stderr = await process.communicate() @@ -46,7 +53,8 @@ async def send_request( method: str, params: Any | None, timeout: int | None = 10, -) -> Any | None: +) -> Any: + logger.debug(f"Send {method} to {runner.working_dir_path}") try: response = await asyncio.wait_for( runner.client.protocol.send_request_async( @@ -70,7 +78,7 @@ async def send_request( # await log_process_log_streams(process=runner.client._server) raise ResponseTimeout( f"Timeout {timeout}s for response on {method} to" - f" runner {runner.working_dir_path}" + f" runner {runner.working_dir_path} in env {runner.env_name}" ) except pygls_exceptions.JsonRpcInternalError as error: logger.error(f"JsonRpcInternalError: {error.message}") @@ -175,16 +183,27 @@ async def run_action( timeout=None, ) + if hasattr(response, "error"): + raise ActionRunFailed(response.error) + return_code = response.return_code raw_result = "" + stringified_result = response.result + # currently result is always dumped to json even if response format is expected to + # be a string. See docs of ER lsp server for more details. + raw_result = json.loads(stringified_result) if response.format == "string": - raw_result = response.result + result = raw_result elif response.format == "json" or response.format == "styled_text_json": - raw_result = json.loads(response.result) + # string was already converted to dict above + result = raw_result else: raise Exception(f"Not support result format: {response.format}") - return RunActionResponse(result=raw_result, return_code=return_code) + if response.status == "stopped": + raise ActionRunStopped(message=result) + + return RunActionResponse(result=result, return_code=return_code) async def reload_action(runner: ExtensionRunnerInfo, action_name: str) -> None: @@ -203,7 +222,9 @@ async def reload_action(runner: ExtensionRunnerInfo, action_name: str) -> None: ) -async def resolve_package_path(runner: ExtensionRunnerInfo, package_name: str) -> dict[str, str]: +async def resolve_package_path( + runner: ExtensionRunnerInfo, package_name: str +) -> dict[str, str]: # resolving package path is used directly after initialization of runner to get full # config, which is then registered in runner. In this time runner is not available # for any other actions, so `runner.started_event` stays not set and should not be @@ -221,10 +242,14 @@ async def resolve_package_path(runner: ExtensionRunnerInfo, package_name: str) - return {"packagePath": response.packagePath} -async def update_config( - runner: ExtensionRunnerInfo, - actions: list[domain.Action], -) -> None: +@dataclasses.dataclass +class RunnerConfig: + actions: list[domain.Action] + # config by handler source + action_handler_configs: dict[str, dict[str, Any]] + + +async def update_config(runner: ExtensionRunnerInfo, config: RunnerConfig) -> None: await send_request( runner=runner, method=types.WORKSPACE_EXECUTE_COMMAND, @@ -233,7 +258,7 @@ async def update_config( arguments=[ runner.working_dir_path.as_posix(), runner.working_dir_path.stem, - actions, + config, ], ), ) diff --git a/src/finecode/workspace_manager/runner/runner_info.py b/src/finecode/runner/runner_info.py similarity index 84% rename from src/finecode/workspace_manager/runner/runner_info.py rename to src/finecode/runner/runner_info.py index 80abf40..b644038 100644 --- a/src/finecode/workspace_manager/runner/runner_info.py +++ b/src/finecode/runner/runner_info.py @@ -1,6 +1,7 @@ from __future__ import annotations import asyncio +import enum import logging import shlex from dataclasses import dataclass @@ -31,6 +32,7 @@ async def start_io(self, cmd: str, *args, **kwargs): stderr=asyncio.subprocess.PIPE, **kwargs, ) + logger.debug(f"{cmd} - process id: {server.pid}") # Keep mypy happy if server.stdout is None: @@ -65,14 +67,25 @@ async def server_exit(self, server): @dataclass class ExtensionRunnerInfo: working_dir_path: Path + env_name: str + status: RunnerStatus # NOTE: initialized doesn't mean the runner is running, check its status initialized_event: asyncio.Event - client: CustomJsonRpcClient + # e.g. if there is no venv for env, client can be None + client: CustomJsonRpcClient | None = None keep_running_request_task: asyncio.Task | None = None @property def process_id(self) -> int: - if self.client._server is not None: + if self.client is not None and self.client._server is not None: return self.client._server.pid else: return 0 + + +class RunnerStatus(enum.Enum): + READY_TO_START = enum.auto() + NO_VENV = enum.auto() + FAILED = enum.auto() + RUNNING = enum.auto() + EXITED = enum.auto() diff --git a/src/finecode/services.py b/src/finecode/services.py new file mode 100644 index 0000000..4e1c7f6 --- /dev/null +++ b/src/finecode/services.py @@ -0,0 +1,185 @@ +import pathlib +import typing + +import ordered_set +from loguru import logger + +from finecode import context, domain, payload_preprocessor, user_messages +from finecode.runner import manager as runner_manager +from finecode.runner import runner_client, runner_info + + +async def restart_extension_runners( + runner_working_dir_path: pathlib.Path, ws_context: context.WorkspaceContext +) -> None: + # TODO: reload config? + try: + runners_by_env = ws_context.ws_projects_extension_runners[ + runner_working_dir_path + ] + except KeyError: + logger.error(f"Cannot find runner for {runner_working_dir_path}") + return + + new_runners_by_env: dict[str, runner_info.ExtensionRunnerInfo] = {} + for runner in runners_by_env.values(): + await runner_manager.stop_extension_runner(runner) + + new_runner = await runner_manager.start_extension_runner( + runner_dir=runner_working_dir_path, + env_name=runner.env_name, + ws_context=ws_context, + ) + if new_runner is None: + logger.error("Extension runner didn't start") + continue + new_runners_by_env[runner.env_name] = new_runner + + ws_context.ws_projects_extension_runners[runner_working_dir_path] = ( + new_runners_by_env + ) + + # parallel? + for runner in new_runners_by_env.values(): + await runner_manager._init_runner( + runner, + ws_context.ws_projects[runner.working_dir_path], + ws_context, + ) + + +def on_shutdown(ws_context: context.WorkspaceContext): + + running_runners = [] + for runners_by_env in ws_context.ws_projects_extension_runners.values(): + for runner in runners_by_env.values(): + if runner.status == runner_info.RunnerStatus.RUNNING: + running_runners.append(runner) + + logger.trace(f"Stop all {len(running_runners)} running extension runners") + + for runner in running_runners: + runner_manager.stop_extension_runner_sync(runner=runner) + + # TODO: stop MCP if running + + +class ActionRunFailed(Exception): + def __init__(self, message: str) -> None: + self.message = message + + +RunResultFormat = runner_client.RunResultFormat +RunActionResponse = runner_client.RunActionResponse + + +async def run_action( + action_name: str, + params: dict[str, typing.Any], + project_def: domain.Project, + ws_context: context.WorkspaceContext, + result_format: RunResultFormat = RunResultFormat.JSON, + preprocess_payload: bool = True, +) -> RunActionResponse: + formatted_params = str(params) + if len(formatted_params) > 100: + formatted_params = f"{formatted_params[:100]}..." + logger.trace(f"Execute action {action_name} with {formatted_params}") + + if project_def.status != domain.ProjectStatus.CONFIG_VALID: + raise ActionRunFailed( + f"Project {project_def.dir_path} has no valid configuration and finecode." + " Please check logs." + ) + + if preprocess_payload: + payload = payload_preprocessor.preprocess_for_project( + action_name=action_name, + payload=params, + project_dir_path=project_def.dir_path, + ws_context=ws_context, + ) + else: + payload = params + + # cases: + # - base: all action handlers are in one env + # -> send `run_action` request to runner in env and let it handle concurrency etc. + # It could be done also in workspace manager, but handlers share run context + # - mixed envs: action handlers are in different envs + # -- concurrent execution of handlers + # -- sequential execution of handlers + assert project_def.actions is not None + action = next( + action for action in project_def.actions if action.name == action_name + ) + all_handlers_envs = ordered_set.OrderedSet( + [handler.env for handler in action.handlers] + ) + all_handlers_are_in_one_env = len(all_handlers_envs) == 1 + + if all_handlers_are_in_one_env: + env_name = all_handlers_envs[0] + response = await _run_action_in_env_runner( + action_name=action_name, + payload=payload, + env_name=env_name, + project_def=project_def, + ws_context=ws_context, + result_format=result_format, + ) + else: + # TODO: concurrent vs sequential, this value should be taken from action config + run_concurrently = False # action_name == 'lint' + if run_concurrently: + ... + raise NotImplementedError() + else: + for handler in action.handlers: + # TODO: manage run context + response = await _run_action_in_env_runner( + action_name=action_name, + payload=payload, + env_name=handler.env, + project_def=project_def, + ws_context=ws_context, + result_format=result_format, + ) + + return response + + +async def _run_action_in_env_runner( + action_name: str, + payload: dict[str, typing.Any], + env_name: str, + project_def: domain.Project, + ws_context: context.WorkspaceContext, + result_format: RunResultFormat = RunResultFormat.JSON, +): + runners_by_env = ws_context.ws_projects_extension_runners[project_def.dir_path] + runner = runners_by_env[env_name] + if runner.status != runner_info.RunnerStatus.RUNNING: + raise ActionRunFailed( + f"Runner {env_name} in project {project_def.dir_path} is not running. Status: {runner.status}" + ) + + try: + response = await runner_client.run_action( + runner=runner, + action_name=action_name, + params=payload, + options={"result_format": result_format}, + ) + except runner_client.BaseRunnerRequestException as error: + runner_log_path = ( + runner.working_dir_path / ".venvs" / runner.env_name / "logs" / "runner.log" + ) + await user_messages.error( + f"Action {action_name} failed in {runner.env_name} of {runner.working_dir_path}: {error.message} . Log file: {runner_log_path}" + ) + raise ActionRunFailed( + f"Action {action_name} failed in {runner.env_name} of {runner.working_dir_path}: {error.message} . Log file: {runner_log_path}" + ) + + return response diff --git a/src/finecode/workspace_manager/user_messages.py b/src/finecode/user_messages.py similarity index 100% rename from src/finecode/workspace_manager/user_messages.py rename to src/finecode/user_messages.py diff --git a/src/finecode/utils/__init__.py b/src/finecode/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/finecode/workspace_manager/utils/async_proc_queue.py b/src/finecode/utils/async_proc_queue.py similarity index 100% rename from src/finecode/workspace_manager/utils/async_proc_queue.py rename to src/finecode/utils/async_proc_queue.py diff --git a/src/finecode/workspace_manager/utils/iterable_subscribe.py b/src/finecode/utils/iterable_subscribe.py similarity index 100% rename from src/finecode/workspace_manager/utils/iterable_subscribe.py rename to src/finecode/utils/iterable_subscribe.py diff --git a/src/finecode/workspace_manager/watch_and_run.py b/src/finecode/watch_and_run.py similarity index 91% rename from src/finecode/workspace_manager/watch_and_run.py rename to src/finecode/watch_and_run.py index 71b3ff2..a5f7586 100644 --- a/src/finecode/workspace_manager/watch_and_run.py +++ b/src/finecode/watch_and_run.py @@ -1,8 +1,8 @@ from loguru import logger -import finecode.workspace_manager.context as context -import finecode.workspace_manager.find_project as find_project -import finecode.workspace_manager.watcher as watcher +import finecode.context as context +import finecode.find_project as find_project +import finecode.watcher as watcher async def watch_and_run( diff --git a/src/finecode/workspace_manager/watcher.py b/src/finecode/watcher.py similarity index 98% rename from src/finecode/workspace_manager/watcher.py rename to src/finecode/watcher.py index cf55747..005e0ff 100644 --- a/src/finecode/workspace_manager/watcher.py +++ b/src/finecode/watcher.py @@ -13,8 +13,8 @@ from watchdog.events import FileSystemEventHandler from watchdog.observers import Observer -import finecode.workspace_manager.context as context -import finecode.workspace_manager.utils.async_proc_queue as async_queue +import finecode.context as context +import finecode.utils.async_proc_queue as async_queue @dataclass diff --git a/src/finecode/workspace_manager/config/dump_configs.py b/src/finecode/workspace_manager/config/dump_configs.py deleted file mode 100644 index 939edcc..0000000 --- a/src/finecode/workspace_manager/config/dump_configs.py +++ /dev/null @@ -1,6 +0,0 @@ -import typing -import tomlkit - - -def dump_config(config: dict[str, typing.Any]) -> str: - return tomlkit.dumps(config) diff --git a/src/finecode/workspace_manager/config/read_configs.py b/src/finecode/workspace_manager/config/read_configs.py deleted file mode 100644 index faaecc9..0000000 --- a/src/finecode/workspace_manager/config/read_configs.py +++ /dev/null @@ -1,296 +0,0 @@ -from pathlib import Path -from typing import Any, NamedTuple - -from loguru import logger -from tomlkit import loads as toml_loads - -from finecode.workspace_manager import context, domain, user_messages -from finecode.workspace_manager.config import config_models -from finecode.workspace_manager.runner import runner_client, runner_info - - -async def read_projects_in_dir( - dir_path: Path, ws_context: context.WorkspaceContext -) -> list[domain.Project]: - # Find all projects in directory - # `dir_path` expected to be absolute path - logger.trace(f"Read directories in {dir_path}") - new_projects: list[domain.Project] = [] - def_files_generator = dir_path.rglob("pyproject.toml") - for def_file in def_files_generator: - # ignore definition files in `__testdata__` directory, projects in test data - # can be started only in tests, not from outside - # TODO: make configurable? - # path to definition file relative to workspace directory in which this - # definition was found - def_file_rel_dir_path = def_file.relative_to(dir_path) - if '__testdata__' in def_file_rel_dir_path.parts: - logger.debug(f"Skip '{def_file}' because it is in test data and it is not a test session") - continue - if def_file.parent.name == 'finecode_config_dump': - logger.debug(f"Skip '{def_file}' because it is config dump, not real project config") - continue - - status = domain.ProjectStatus.READY - actions: list[domain.Action] | None = None - - with open(def_file, "rb") as pyproject_file: - project_def = toml_loads(pyproject_file.read()).value - - if project_def.get("tool", {}).get("finecode", None) is None: - status = domain.ProjectStatus.NO_FINECODE - actions = [] - else: - # finecode config exists, check also finecode.sh - finecode_sh_path = def_file.parent / "finecode.sh" - - if not finecode_sh_path.exists(): - status = domain.ProjectStatus.NO_FINECODE_SH - - new_project = domain.Project( - name=def_file.parent.name, - dir_path=def_file.parent, - def_path=def_file, - status=status, - actions=actions, - ) - ws_context.ws_projects[def_file.parent] = new_project - new_projects.append(new_project) - return new_projects - - -async def read_project_config( - project: domain.Project, ws_context: context.WorkspaceContext -) -> None: - # this function requires running project extension runner to get configuration - # from it - if project.def_path.name == "pyproject.toml": - with open(project.def_path, "rb") as pyproject_file: - # TODO: handle error if toml is invalid - project_def = toml_loads(pyproject_file.read()).value - # TODO: validate that finecode is installed? - - finecode_raw_config = project_def.get("tool", {}).get("finecode", None) - if finecode_raw_config: - finecode_config = config_models.FinecodeConfig(**finecode_raw_config) - new_config = await collect_config_from_py_presets( - presets_sources=[preset.source for preset in finecode_config.presets], - def_path=project.def_path, - runner=ws_context.ws_projects_extension_runners[project.dir_path], - ) - _merge_projects_configs(project_def, new_config) - - ws_context.ws_projects_raw_configs[project.dir_path] = project_def - else: - logger.info( - f"Project definition of type {project.def_path.name} is not supported yet" - ) - - -class PresetToProcess(NamedTuple): - source: str - project_def_path: Path - - -async def get_preset_project_path( - preset: PresetToProcess, def_path: Path, runner: runner_info.ExtensionRunnerInfo -) -> Path | None: - logger.trace(f"Get preset project path: {preset.source}") - - try: - resolve_path_result = await runner_client.resolve_package_path( - runner, preset.source - ) - except runner_client.BaseRunnerRequestException as error: - await user_messages.error(f"Failed to get preset project path: {error.message}") - return None - try: - preset_project_path = Path(resolve_path_result["packagePath"]) - except KeyError: - raise ValueError(f"Preset source cannot be resolved: {preset.source}") - - logger.trace(f"Got: {preset.source} -> {preset_project_path}") - return preset_project_path - - -def read_preset_config( - config_path: Path, preset_id: str -) -> tuple[dict[str, Any] | None, config_models.PresetDefinition | None]: - # preset_id is used only for logs to make them more useful - logger.trace(f"Read preset config: {preset_id}") - if not config_path.exists(): - logger.error(f"preset.toml not found in project '{preset_id}'") - return (None, None) - - with open(config_path, "rb") as preset_toml_file: - preset_toml = toml_loads(preset_toml_file.read()).value - - try: - presets = preset_toml["tool"]["finecode"]["presets"] - except KeyError: - presets = [] - - preset_config = config_models.PresetDefinition(extends=presets) - - logger.trace(f"Reading preset config finished: {preset_id}") - return (preset_toml, preset_config) - - -async def collect_config_from_py_presets( - presets_sources: list[str], def_path: Path, runner: runner_info.ExtensionRunnerInfo -) -> dict[str, Any]: - config: dict[str, Any] = {} - processed_presets: set[str] = set() - presets_to_process: set[PresetToProcess] = set( - [ - PresetToProcess(source=preset_source, project_def_path=def_path) - for preset_source in presets_sources - ] - ) - while len(presets_to_process) > 0: - preset = presets_to_process.pop() - processed_presets.add(preset.source) - - preset_project_path = await get_preset_project_path( - preset=preset, def_path=def_path, runner=runner - ) - if preset_project_path is None: - logger.trace(f"Path of preset {preset.source} not found") - continue - - preset_toml_path = preset_project_path / "preset.toml" - preset_toml, preset_config = read_preset_config(preset_toml_path, preset.source) - if preset_toml is None or preset_config is None: - continue - - _merge_preset_configs(config, preset_toml) - new_presets_sources = ( - set([extend.source for extend in preset_config.extends]) - processed_presets - ) - for new_preset_source in new_presets_sources: - presets_to_process.add( - PresetToProcess( - source=new_preset_source, - project_def_path=def_path, - ) - ) - - return config - - -def _merge_projects_configs(config1: dict[str, Any], config2: dict[str, Any]) -> None: - # merge config2 in config1 without overwriting - if "tool" not in config1: - config1["tool"] = {} - if "finecode" not in config1["tool"]: - config1["tool"]["finecode"] = {} - - tool_finecode_config1 = config1["tool"]["finecode"] - tool_finecode_config2 = config2.get("tool", {}).get("finecode", {}) - - for key, value in tool_finecode_config2.items(): - if key == "action" or key == "action_handler": - # first process actions explicitly to merge correct configs - assert isinstance(value, dict) - if key not in tool_finecode_config1: - tool_finecode_config1[key] = {} - for action_name, action_info in value.items(): - if action_name not in tool_finecode_config1[key]: - # new action, just add as it is - tool_finecode_config1[key][action_name] = action_info - else: - # action with the same name, merge - if "config" in action_info: - if "config" not in tool_finecode_config1[key][action_name]: - tool_finecode_config1[key][action_name]["config"] = {} - - action_config = tool_finecode_config1[key][action_name][ - "config" - ] - action_config.update(action_info["config"]) - elif key in config1: - tool_finecode_config1[key].update(value) - else: - tool_finecode_config1[key] = value - - -def _merge_preset_configs(config1: dict[str, Any], config2: dict[str, Any]) -> None: - # merge config2 in config1 (in-place) - # config1 is not overwritten by config2 - new_views = config2.get("tool", {}).get("finecode", {}).get("views", None) - new_actions_defs_and_configs = ( - config2.get("tool", {}).get("finecode", {}).get("action", None) - ) - new_actions_handlers_configs = ( - config2.get("tool", {}).get("finecode", {}).get("action_handler", None) - ) - if ( - new_views is not None - or new_actions_defs_and_configs is not None - or new_actions_handlers_configs is not None - ): - if "tool" not in config1: - config1["tool"] = {} - if "finecode" not in config1["tool"]: - config1["tool"]["finecode"] = {} - - if new_views is not None: - if "views" not in config1["tool"]["finecode"]: - config1["tool"]["finecode"]["views"] = [] - config1["tool"]["finecode"]["views"].extend(new_views) - del config2["tool"]["finecode"]["views"] - - if new_actions_defs_and_configs is not None: - if "action" not in config1["tool"]["finecode"]: - config1["tool"]["finecode"]["action"] = {} - - for handler_name, handler_info in new_actions_defs_and_configs.items(): - if handler_name not in config1["tool"]["finecode"]["action"]: - config1["tool"]["finecode"]["action"][handler_name] = {} - - action_def = { - key: value for key, value in handler_info.items() if key != "config" - } - config1["tool"]["finecode"]["action"][handler_name].update(action_def) - - try: - handler_config = handler_info["config"] - except KeyError: - continue - - handler_config.update( - config1["tool"]["finecode"]["action"][handler_name].get( - "config", {} - ) - ) - config1["tool"]["finecode"]["action"][handler_name][ - "config" - ] = handler_config - - del config2["tool"]["finecode"]["action"] - - if new_actions_handlers_configs is not None: - if "action_handler" not in config1["tool"]["finecode"]: - config1["tool"]["finecode"]["action_handler"] = {} - - for handler_name, handler_info in new_actions_handlers_configs.items(): - if handler_name not in config1["tool"]["finecode"]["action_handler"]: - config1["tool"]["finecode"]["action_handler"][handler_name] = {} - - try: - handler_config = handler_info["config"] - except KeyError: - continue - - handler_config.update( - config1["tool"]["finecode"]["action_handler"][handler_name].get( - "config", {} - ) - ) - config1["tool"]["finecode"]["action_handler"][handler_name][ - "config" - ] = handler_config - - del config2["tool"]["finecode"]["action_handler"] - - del config2["tool"]["finecode"] diff --git a/src/finecode/workspace_manager/finecode_cmd.py b/src/finecode/workspace_manager/finecode_cmd.py deleted file mode 100644 index 5cd2114..0000000 --- a/src/finecode/workspace_manager/finecode_cmd.py +++ /dev/null @@ -1,13 +0,0 @@ -from pathlib import Path - - -def get_finecode_cmd(project_path: Path) -> str: - sh_path = project_path / "finecode.sh" - - if not sh_path.exists(): - raise ValueError(f"finecode.sh not found in project {project_path}") - - with open(sh_path, "r") as sh_file: - sh_cmd = sh_file.readline() - - return sh_cmd diff --git a/src/finecode/workspace_manager/payload_preprocessor.py b/src/finecode/workspace_manager/payload_preprocessor.py deleted file mode 100644 index f8e5dbd..0000000 --- a/src/finecode/workspace_manager/payload_preprocessor.py +++ /dev/null @@ -1,26 +0,0 @@ -import pathlib -import typing - -from finecode.workspace_manager import project_analyzer - - -def preprocess_for_project( - action_name: str, payload: dict[str, typing.Any], project_dir_path: pathlib.Path -) -> dict[str, typing.Any]: - processed_payload = payload.copy() - - # temporary hardcore logic until we get the proper payload structure and defaults - # from extension runner - if action_name == "lint" or action_name == "format": - if "file_paths" not in processed_payload: - processed_payload["file_paths"] = None - if "save" not in processed_payload: - processed_payload["save"] = True - - for param, value in processed_payload.items(): - if param == "file_paths" and value is None: - processed_payload["file_paths"] = project_analyzer.get_project_files( - project_dir_path - ) - - return processed_payload diff --git a/src/finecode/workspace_manager/runner/manager.py b/src/finecode/workspace_manager/runner/manager.py deleted file mode 100644 index a5b0fb8..0000000 --- a/src/finecode/workspace_manager/runner/manager.py +++ /dev/null @@ -1,340 +0,0 @@ -import asyncio -import json -import os -from pathlib import Path -from typing import Callable, Coroutine - -from loguru import logger -from lsprotocol import types - -from finecode import dirs_utils -from finecode.pygls_client_utils import create_lsp_client_io -from finecode.workspace_manager import context, domain, finecode_cmd -from finecode.workspace_manager.config import collect_actions, read_configs -from finecode.workspace_manager.runner import runner_client, runner_info -from finecode.workspace_manager.utils import iterable_subscribe - -project_changed_callback: ( - Callable[[domain.Project], Coroutine[None, None, None]] | None -) = None -get_document: Callable[[], Coroutine] | None = None -apply_workspace_edit: Callable[[], Coroutine] | None = None -partial_results: iterable_subscribe.IterableSubscribe = ( - iterable_subscribe.IterableSubscribe() -) - - -class RunnerFailedToStart(Exception): - def __init__(self, message: str) -> None: - self.message = message - - -async def notify_project_changed(project: domain.Project) -> None: - if project_changed_callback is not None: - await project_changed_callback(project) - - -async def _apply_workspace_edit(params: types.ApplyWorkspaceEditParams): - def map_change_object(change): - return types.TextEdit( - range=types.Range( - start=types.Position( - line=change.range.start.line, character=change.range.start.character - ), - end=types.Position( - change.range.end.line, character=change.range.end.character - ), - ), - new_text=change.newText, - ) - - converted_params = types.ApplyWorkspaceEditParams( - edit=types.WorkspaceEdit( - document_changes=[ - types.TextDocumentEdit( - text_document=types.OptionalVersionedTextDocumentIdentifier( - document_edit.textDocument.uri - ), - edits=[map_change_object(change) for change in document_edit.edits], - ) - for document_edit in params.edit.documentChanges - ] - ) - ) - return await apply_workspace_edit(converted_params) - - -async def start_extension_runner( - runner_dir: Path, ws_context: context.WorkspaceContext -) -> runner_info.ExtensionRunnerInfo | None: - try: - _finecode_cmd = finecode_cmd.get_finecode_cmd(runner_dir) - except ValueError: - try: - ws_context.ws_projects[runner_dir].status = ( - domain.ProjectStatus.NO_FINECODE_SH - ) - await notify_project_changed(ws_context.ws_projects[runner_dir]) - except KeyError: - ... - return None - - process_args: list[str] = [ - "--trace", - f"--project-path={runner_dir.as_posix()}", - ] - # TODO: config parameter for debug and debug port - # if runner_dir == Path("/home/user/Development/FineCode/finecode"): - # process_args.append("--debug") - # process_args.append("--debug-port=5681") - - process_args_str: str = " ".join(process_args) - client = await create_lsp_client_io( - runner_info.CustomJsonRpcClient, - f"{_finecode_cmd} -m finecode.extension_runner.cli {process_args_str}", - runner_dir, - ) - runner_info_instance = runner_info.ExtensionRunnerInfo( - working_dir_path=runner_dir, initialized_event=asyncio.Event(), client=client - ) - - async def on_exit(): - logger.debug(f"Extension Runner {runner_info_instance.working_dir_path} exited") - ws_context.ws_projects[runner_dir].status = domain.ProjectStatus.EXITED - await notify_project_changed(ws_context.ws_projects[runner_dir]) - # TODO: restart if WM is not stopping - - runner_info_instance.client.server_exit_callback = on_exit - - if get_document is not None: - register_get_document_feature = runner_info_instance.client.feature( - "documents/get" - ) - register_get_document_feature(get_document) - - register_workspace_apply_edit = runner_info_instance.client.feature( - types.WORKSPACE_APPLY_EDIT - ) - register_workspace_apply_edit(_apply_workspace_edit) - - async def on_progress(params: types.ProgressParams): - logger.debug(f"Got progress from runner for token: {params.token}") - partial_result = domain.PartialResult( - token=params.token, value=json.loads(params.value) - ) - partial_results.publish(partial_result) - - register_progress_feature = runner_info_instance.client.feature(types.PROGRESS) - register_progress_feature(on_progress) - - return runner_info_instance - - -async def stop_extension_runner(runner: runner_info.ExtensionRunnerInfo) -> None: - logger.trace(f"Trying to stop extension runner {runner.working_dir_path}") - if not runner.client.stopped: - logger.debug("Send shutdown to server") - try: - await runner_client.shutdown(runner=runner) - except Exception as e: - # TODO: handle - logger.error(f"Failed to shutdown {e}") - - await runner_client.exit(runner) - logger.debug("Sent exit to server") - await runner.client.stop() - logger.trace( - f"Stop extension runner {runner.process_id}" - f" in {runner.working_dir_path}" - ) - else: - logger.trace("Extension runner was not running") - - -def stop_extension_runner_sync(runner: runner_info.ExtensionRunnerInfo) -> None: - logger.trace(f"Trying to stop extension runner {runner.working_dir_path}") - if not runner.client.stopped: - logger.debug("Send shutdown to server") - try: - runner_client.shutdown_sync(runner=runner) - except Exception as e: - # TODO: handle - logger.error(f"Failed to shutdown {e}") - - runner_client.exit_sync(runner) - logger.debug("Sent exit to server") - logger.trace( - f"Stop extension runner {runner.process_id}" - f" in {runner.working_dir_path}" - ) - else: - logger.trace("Extension runner was not running") - - -async def kill_extension_runner(runner: runner_info.ExtensionRunnerInfo) -> None: - if runner.client._server is not None: - runner.client._server.terminate() - await runner.client.stop() - - -async def update_runners(ws_context: context.WorkspaceContext) -> None: - # starts runners for new(=which don't have runner yet) projects in `ws_context` - # and stops runners for projects which are not in `ws_context` anymore - # - # during initialization of new runners it also reads their configurations and - # actions - # - # this function should handle all possible statuses of projects and they either - # start of fail to start, only projects without finecode are ignored - extension_runners = list(ws_context.ws_projects_extension_runners.values()) - new_dirs, deleted_dirs = dirs_utils.find_changed_dirs( - [*ws_context.ws_projects.keys()], - [runner.working_dir_path for runner in extension_runners], - ) - for deleted_dir in deleted_dirs: - try: - runner_to_delete = next( - runner - for runner in extension_runners - if runner.working_dir_path == deleted_dir - ) - except StopIteration: - continue - await stop_extension_runner(runner_to_delete) - extension_runners.remove(runner_to_delete) - - new_runners_tasks: list[asyncio.Task] = [] - try: - async with asyncio.TaskGroup() as tg: - for new_dir in new_dirs: - project = ws_context.ws_projects[new_dir] - project_status = project.status - if project_status == domain.ProjectStatus.READY: - runner_task = tg.create_task(start_extension_runner(runner_dir=new_dir, ws_context=ws_context)) - new_runners_tasks.append(runner_task) - elif project_status != domain.ProjectStatus.NO_FINECODE: - raise RunnerFailedToStart(f"Runner for project '{project.name}' failed to start, status: {project_status.name}") - except ExceptionGroup as eg: - for exception in eg.exceptions: - if isinstance(exception, runner_client.BaseRunnerRequestException) or isinstance(exception, RunnerFailedToStart): - logger.error(exception.message) - else: - logger.exception(exception) - raise RunnerFailedToStart("Failed to start runner") - - extension_runners += [ - runner.result() for runner in new_runners_tasks if runner is not None - ] - - ws_context.ws_projects_extension_runners = { - runner.working_dir_path: runner for runner in extension_runners - } - - try: - async with asyncio.TaskGroup() as tg: - for runner in extension_runners: - tg.create_task( - _init_runner( - runner, - ws_context.ws_projects[runner.working_dir_path], - ws_context, - ) - ) - except ExceptionGroup as eg: - for exception in eg.exceptions: - if isinstance(exception, runner_client.BaseRunnerRequestException): - logger.error(exception.message) - else: - logger.exception(exception) - raise RunnerFailedToStart("Failed to initialize runner") - - -async def _init_runner( - runner: runner_info.ExtensionRunnerInfo, - project: domain.Project, - ws_context: context.WorkspaceContext, -) -> None: - # initialization is required to be able to perform other requests - logger.trace(f"Init runner {runner.working_dir_path}") - try: - await runner_client.initialize( - runner, - client_process_id=os.getpid(), - client_name="FineCode_WorkspaceManager", - client_version="0.1.0", - ) - except runner_client.BaseRunnerRequestException as error: - project.status = domain.ProjectStatus.RUNNER_FAILED - await notify_project_changed(project) - runner.initialized_event.set() - raise RunnerFailedToStart(f"Runner failed to initialize: {error.message}") - - try: - await runner_client.notify_initialized(runner) - except Exception as error: - logger.error(f"Failed to notify runner about initialization: {error}") - project.status = domain.ProjectStatus.RUNNER_FAILED - await notify_project_changed(project) - runner.initialized_event.set() - logger.exception(error) - raise RunnerFailedToStart( - f"Runner failed to notify about initialization: {error}" - ) - - logger.debug("LSP Server initialized") - - await read_configs.read_project_config(project=project, ws_context=ws_context) - collect_actions.collect_actions( - project_path=project.dir_path, ws_context=ws_context - ) - - assert ( - project.actions is not None - ), f"Actions of project {project.dir_path} are not read yet" - - try: - await runner_client.update_config(runner, project.actions) - except runner_client.BaseRunnerRequestException as exception: - project.status = domain.ProjectStatus.RUNNER_FAILED - await notify_project_changed(project) - runner.initialized_event.set() - raise RunnerFailedToStart(f"Runner failed to update config: {exception.message}") - - logger.debug( - f"Updated config of runner {runner.working_dir_path}," - f" process id {runner.process_id}" - ) - project.status = domain.ProjectStatus.RUNNING - await notify_project_changed(project) - - await send_opened_files( - runner=runner, opened_files=list(ws_context.opened_documents.values()) - ) - - runner.initialized_event.set() - - -async def send_opened_files( - runner: runner_info.ExtensionRunnerInfo, opened_files: list[domain.TextDocumentInfo] -): - files_for_runner: list[domain.TextDocumentInfo] = [] - for opened_file_info in opened_files: - file_path = Path(opened_file_info.uri.replace("file://", "")) - if not file_path.is_relative_to(runner.working_dir_path): - continue - else: - files_for_runner.append(opened_file_info) - - try: - async with asyncio.TaskGroup() as tg: - for file_info in files_for_runner: - tg.create_task( - runner_client.notify_document_did_open( - runner=runner, - document_info=domain.TextDocumentInfo( - uri=file_info.uri, version=file_info.version - ), - ) - ) - except ExceptionGroup as eg: - logger.error(f"Error while sending opened document: {eg.exceptions}") diff --git a/src/finecode/workspace_manager/services.py b/src/finecode/workspace_manager/services.py deleted file mode 100644 index 1a69aea..0000000 --- a/src/finecode/workspace_manager/services.py +++ /dev/null @@ -1,99 +0,0 @@ -import pathlib -import typing - -from loguru import logger - -from finecode.workspace_manager import ( - context, - domain, - payload_preprocessor, - user_messages, -) -from finecode.workspace_manager.runner import manager as runner_manager -from finecode.workspace_manager.runner import runner_client - - -async def restart_extension_runner( - runner_working_dir_path: pathlib.Path, ws_context: context.WorkspaceContext -) -> None: - # TODO: reload config? - try: - runner = ws_context.ws_projects_extension_runners[runner_working_dir_path] - except KeyError: - logger.error(f"Cannot find runner for {runner_working_dir_path}") - return - - await runner_manager.stop_extension_runner(runner) - del ws_context.ws_projects_extension_runners[runner_working_dir_path] - - new_runner = await runner_manager.start_extension_runner( - runner_dir=runner_working_dir_path, ws_context=ws_context - ) - if new_runner is None: - logger.error("Extension runner didn't start") - return - - ws_context.ws_projects_extension_runners[runner_working_dir_path] = new_runner - await runner_manager._init_runner( - new_runner, - ws_context.ws_projects[runner.working_dir_path], - ws_context, - ) - - -def on_shutdown(ws_context: context.WorkspaceContext): - running_runners = [ - runner - for runner in ws_context.ws_projects_extension_runners.values() - if ws_context.ws_projects[runner.working_dir_path].status - == domain.ProjectStatus.RUNNING - ] - logger.trace(f"Stop all {len(running_runners)} running extension runners") - - for runner in running_runners: - runner_manager.stop_extension_runner_sync(runner=runner) - - -RunResultFormat = runner_client.RunResultFormat -RunActionResponse = runner_client.RunActionResponse - - -async def run_action( - action_name: str, - params: dict[str, typing.Any], - project_def: domain.Project, - ws_context: context.WorkspaceContext, - result_format: RunResultFormat = RunResultFormat.JSON, -) -> RunActionResponse: - formatted_params = str(params) - if len(formatted_params) > 100: - formatted_params = f"{formatted_params[:100]}..." - logger.trace(f"Execute action {action_name} with {formatted_params}") - - if project_def.status != domain.ProjectStatus.RUNNING: - logger.error( - f"Extension runner is not running in {project_def.dir_path}." - " Please check logs." - ) - return RunActionResponse(result={}, return_code=1) - - payload = payload_preprocessor.preprocess_for_project( - action_name=action_name, payload=params, project_dir_path=project_def.dir_path - ) - - # extension runner is running for this project, send command to it - try: - response = await runner_client.run_action( - runner=ws_context.ws_projects_extension_runners[project_def.dir_path], - action_name=action_name, - params=payload, - options={"result_format": result_format}, - ) - except runner_client.BaseRunnerRequestException as error: - await user_messages.error(f"Action {action_name} failed: {error.message}") - if result_format == runner_client.RunResultFormat.JSON: - return RunActionResponse(result={}, return_code=1) - else: - return RunActionResponse(result="", return_code=1) - - return response diff --git a/tests/__testdata__/list_ws/cli_tool/finecode.sh b/tests/__testdata__/list_ws/cli_tool/finecode.sh deleted file mode 100644 index 176acc2..0000000 --- a/tests/__testdata__/list_ws/cli_tool/finecode.sh +++ /dev/null @@ -1 +0,0 @@ -poetry run python \ No newline at end of file diff --git a/tests/__testdata__/list_ws/ui_app/finecode.sh b/tests/__testdata__/list_ws/ui_app/finecode.sh deleted file mode 100644 index 176acc2..0000000 --- a/tests/__testdata__/list_ws/ui_app/finecode.sh +++ /dev/null @@ -1 +0,0 @@ -poetry run python \ No newline at end of file diff --git a/tests/__testdata__/nested_package/pyback/finecode.sh b/tests/__testdata__/nested_package/pyback/finecode.sh deleted file mode 100644 index 176acc2..0000000 --- a/tests/__testdata__/nested_package/pyback/finecode.sh +++ /dev/null @@ -1 +0,0 @@ -poetry run python \ No newline at end of file