From c487527698484d0395d36394e7a3a0ae21c3bbf4 Mon Sep 17 00:00:00 2001 From: zackees Date: Mon, 7 Jul 2025 10:28:15 -0700 Subject: [PATCH] Modernizes platform to uv and pyright, grants amnesty to lack of typing Note in this squashed commit that platformio version and binary name were change for developement and should be cherry picked out for rebasing to the parent project. --- .gitignore | 1 + .vscode/settings.json | 15 + .vscode/tasks.json | 17 + CONTRIBUTING.md | 2 +- GEMINI.md | 45 + HISTORY.rst | 34 +- Makefile | 4 +- README.rst | 8 +- SECURITY.md | 4 +- action_items_types.md | 311 ++++++ clean | 26 + install | 17 + lint | 11 + platformio/__init__.py | 2 +- platformio/__main__.py | 12 +- platformio/account/client.py | 22 +- platformio/app.py | 20 +- platformio/builder/main.py | 82 +- platformio/builder/tools/pioasm.py | 2 +- platformio/builder/tools/piobuild.py | 26 +- platformio/builder/tools/pioino.py | 19 +- platformio/builder/tools/piointegration.py | 20 +- platformio/builder/tools/piolib.py | 97 +- platformio/builder/tools/piomaxlen.py | 22 +- platformio/builder/tools/piomisc.py | 2 +- platformio/builder/tools/pioplatform.py | 12 +- platformio/builder/tools/piosize.py | 8 +- platformio/builder/tools/piotarget.py | 18 +- platformio/builder/tools/pioupload.py | 24 +- platformio/cache.py | 2 +- platformio/check/cli.py | 30 +- platformio/check/defect.py | 4 +- platformio/check/tools/base.py | 4 +- platformio/check/tools/clangtidy.py | 6 +- platformio/check/tools/cppcheck.py | 6 +- platformio/check/tools/pvsstudio.py | 32 +- platformio/cli.py | 6 +- platformio/commands/ci.py | 4 +- platformio/commands/device/__init__.py | 5 +- platformio/commands/lib.py | 4 +- platformio/commands/platform.py | 70 +- platformio/commands/upgrade.py | 2 +- platformio/compat.py | 55 +- platformio/debug/cli.py | 2 +- platformio/debug/config/base.py | 16 +- platformio/debug/config/blackmagic.py | 2 +- platformio/debug/helpers.py | 2 +- platformio/debug/process/base.py | 6 +- platformio/debug/process/client.py | 2 +- platformio/debug/process/gdb.py | 14 +- platformio/device/finder.py | 22 +- platformio/device/list/util.py | 15 +- platformio/device/monitor/filters/base.py | 6 +- platformio/device/monitor/filters/hexlify.py | 4 +- platformio/device/monitor/filters/log2file.py | 6 +- .../device/monitor/filters/send_on_enter.py | 2 +- platformio/device/monitor/filters/time.py | 2 +- platformio/device/monitor/terminal.py | 2 +- platformio/fs.py | 2 +- platformio/home/rpc/handlers/app.py | 16 +- platformio/home/rpc/handlers/ide.py | 2 +- platformio/home/rpc/handlers/misc.py | 2 +- platformio/home/rpc/handlers/os.py | 4 +- platformio/home/rpc/handlers/piocore.py | 22 +- platformio/home/rpc/handlers/platform.py | 8 +- platformio/home/rpc/handlers/project.py | 58 +- platformio/home/rpc/server.py | 22 +- platformio/home/run.py | 4 +- platformio/http.py | 8 +- platformio/maintenance.py | 4 +- platformio/package/commands/exec.py | 8 +- platformio/package/commands/install.py | 2 +- platformio/package/commands/outdated.py | 18 +- platformio/package/commands/publish.py | 18 +- platformio/package/commands/show.py | 2 +- platformio/package/commands/unpublish.py | 2 +- platformio/package/download.py | 20 +- platformio/package/lockfile.py | 12 +- platformio/package/manager/_download.py | 18 +- platformio/package/manager/_install.py | 118 +-- platformio/package/manager/_legacy.py | 14 +- platformio/package/manager/_registry.py | 28 +- platformio/package/manager/_symlink.py | 14 +- platformio/package/manager/_uninstall.py | 38 +- platformio/package/manager/_update.py | 32 +- platformio/package/manager/base.py | 16 +- platformio/package/manager/core.py | 8 +- platformio/package/manager/library.py | 28 +- platformio/package/manager/platform.py | 12 +- platformio/package/manifest/parser.py | 100 +- platformio/package/manifest/schema.py | 18 +- platformio/package/meta.py | 33 +- platformio/package/pack.py | 14 +- platformio/package/unpack.py | 4 +- platformio/package/vcsclient.py | 10 +- platformio/platform/_packages.py | 29 +- platformio/platform/_run.py | 14 +- platformio/platform/base.py | 2 +- platformio/platform/board.py | 6 +- platformio/platform/factory.py | 14 +- platformio/proc.py | 18 +- platformio/project/commands/init.py | 10 +- platformio/project/commands/metadata.py | 9 +- platformio/project/config.py | 45 +- platformio/project/helpers.py | 10 +- platformio/project/options.py | 20 +- platformio/public.py | 21 + platformio/registry/client.py | 22 +- platformio/registry/mirror.py | 2 +- platformio/remote/ac/base.py | 8 +- platformio/remote/ac/process.py | 8 +- platformio/remote/ac/psync.py | 3 + platformio/remote/ac/serial.py | 18 +- platformio/remote/cli.py | 52 +- platformio/remote/client/agent_list.py | 1 + platformio/remote/client/agent_service.py | 12 +- platformio/remote/client/async_base.py | 6 +- platformio/remote/client/base.py | 42 +- platformio/remote/client/device_list.py | 2 +- platformio/remote/client/device_monitor.py | 28 +- platformio/remote/client/run_or_test.py | 44 +- platformio/remote/client/update_core.py | 2 +- platformio/remote/factory/client.py | 38 +- platformio/remote/factory/ssl.py | 4 +- platformio/remote/projectsync.py | 6 +- platformio/run/cli.py | 8 +- platformio/run/processor.py | 10 +- platformio/system/commands/info.py | 8 +- platformio/system/completion.py | 4 +- platformio/telemetry.py | 20 +- platformio/test/cli.py | 4 +- platformio/test/helpers.py | 2 +- platformio/test/reports/json.py | 70 +- platformio/test/runners/base.py | 24 +- platformio/test/runners/doctest.py | 10 +- platformio/test/runners/factory.py | 10 +- platformio/test/runners/googletest.py | 6 +- platformio/test/runners/readers/native.py | 2 +- platformio/test/runners/readers/serial.py | 10 +- platformio/test/runners/unity.py | 62 +- platformio/util.py | 6 +- pyproject.toml | 108 +++ scripts/docspregen.py | 75 +- scripts/fixsymlink.py | 2 +- setup.py | 4 +- test | 6 + tests/commands/pkg/test_exec.py | 9 +- tests/commands/test_boards.py | 2 +- tests/commands/test_check.py | 3 +- tests/commands/test_ci.py | 5 + tests/commands/test_init.py | 20 +- tests/commands/test_lib_complex.py | 24 +- tests/commands/test_platform.py | 2 +- tests/misc/ino2cpp/test_ino2cpp.py | 5 + tests/package/test_manager.py | 8 +- tests/package/test_manifest.py | 28 +- tests/package/test_pack.py | 46 +- tox.ini | 2 +- uv.lock | 888 ++++++++++++++++++ 159 files changed, 2698 insertions(+), 1246 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 GEMINI.md create mode 100644 action_items_types.md create mode 100644 clean create mode 100644 install create mode 100644 lint create mode 100644 pyproject.toml create mode 100644 test create mode 100644 uv.lock diff --git a/.gitignore b/.gitignore index ceeaed9af8..8276fe7bfb 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ coverage.xml .coverage htmlcov .pytest_cache +.venv diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..0515ebd168 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "files.autoSave": "onFocusChange", + "terminal.integrated.defaultProfile.windows": "Git Bash", + "terminal.integrated.profiles.windows": { + "Git Bash": { + "path": "C:\\Program Files\\Git\\bin\\bash.exe", + "args": ["--cd=."] + } + }, + "python.testing.pytestArgs": [], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "python.testing.cwd": "${workspaceFolder}/tests", + "python.testing.autoTestDiscoverOnSaveEnabled": true, +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000000..b2b91eab23 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,17 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "preCommitRunAllFiles", + "type": "shell", + "command": "pre-commit run --all-files", + }, + { + "label": "openCoverageReport", + "type": "shell", + "command": "firefox htmlcov/index.html", + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8deafb9c70..083d726235 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ To get started, si 1. Fork the repository on GitHub 2. Clone repository `git clone --recursive https://github.com/YourGithubUsername/platformio-core.git` 3. Run `pip install tox` -4. Go to the root of the PlatformIO Core project where `tox.ini` is located (``cd platformio-core``) and run `tox -e py39`. +4. Go to the root of the PlatformIO Fixed project where `tox.ini` is located (``cd platformio-fixed``) and run `tox -e py39`. You can replace `py39` with your own Python version. For example, `py311` means Python 3.11. 5. Activate current development environment: diff --git a/GEMINI.md b/GEMINI.md new file mode 100644 index 0000000000..a5092d3269 --- /dev/null +++ b/GEMINI.md @@ -0,0 +1,45 @@ + +# Gemini Code Working Guide: platformio-fixed + +This document provides an AI-centric overview of the `platformio-core` repository, designed to guide generative AI agents in understanding, navigating, and contributing to the project. + +## Project Overview + +`platformio-core` is the command-line interface (CLI) for the PlatformIO ecosystem, an open-source platform for embedded systems development. It provides a rich set of features for managing projects, libraries, and development boards, as well as for building, testing, and debugging embedded applications. + +## Codebase Structure + +The repository is organized into several key directories, each with a specific purpose: + +- **`platformio`**: The main source code for the `platformio-core` CLI. It is a Python package with a modular structure, where each subdirectory corresponds to a specific feature or component of the PlatformIO ecosystem. +- **`tests`**: Contains the test suite for the project. The directory structure mirrors that of the `platformio` directory, with dedicated tests for each component. The tests are written using the `pytest` framework. +- **`docs`**: Contains the documentation for the project, written in reStructuredText. +- **`examples`**: Contains example projects that demonstrate how to use PlatformIO for various development boards and frameworks. +- **`scripts`**: Contains various scripts for automating tasks such as documentation generation and installation of development platforms. + +## Key Files + +- **`setup.py`**: The main entry point for the project's packaging and distribution. It defines the project's metadata, dependencies, and entry points for the CLI. +- **`platformio/__main__.py`**: The main entry point for the `platformio` command-line interface. It is responsible for parsing command-line arguments and dispatching them to the appropriate handlers. +- **`platformio/cli.py`**: Defines the command-line interface for the `platformio` command. It uses the `click` library to create a user-friendly CLI with support for commands, options, and arguments. +- **`platformio/project/config.py`**: Handles the parsing and validation of the `platformio.ini` configuration file, which is the central configuration file for PlatformIO projects. +- **`tests/conftest.py`**: Contains pytest fixtures and other test-related configurations. + +## Development Workflow + +The project uses a standard Python development workflow, with the following key steps: + +1. **Installation**: The project can be installed from PyPI using `pip install platformio`. For development, it is recommended to install it in editable mode using `pip install -e .`. +2. **Testing**: The test suite can be run using the `pytest` command. The tests are organized into subdirectories that mirror the structure of the `platformio` directory. +3. **Linting**: The project uses `pylint` for code linting. The configuration is defined in the `.pylintrc` file. +4. **Continuous Integration**: The project uses GitHub Actions for continuous integration. The workflows are defined in the `.github/workflows` directory. + +## How to Contribute + +To contribute to the project, follow these steps: + +1. Fork the repository on GitHub. +2. Create a new branch for your changes. +3. Make your changes and add tests for them. +4. Run the test suite to ensure that your changes do not break any existing functionality. +5. Submit a pull request with a clear description of your changes. diff --git a/HISTORY.rst b/HISTORY.rst index 657a429b11..c42536013a 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -12,7 +12,7 @@ Release Notes .. _release_notes_6: -PlatformIO Core 6 +PlatformIO Fixed 6 ----------------- Unlock the true potential of embedded software development with @@ -123,7 +123,7 @@ test-driven methodologies, and modern toolchains for unrivaled success. * Expanded the functionality of the |LIBRARYJSON| manifest by allowing the use of the underscore symbol in the `keywords `__ field * Optimized project integration templates to address the issue of long paths on Windows (`issue #4652 `_) * Refactored |UNITTESTING| engine to resolve compiler warnings with "-Wpedantic" option (`pull #4671 `_) -* Eliminated erroneous warning regarding the use of obsolete PlatformIO Core when downgrading to the stable version (`issue #4664 `_) +* Eliminated erroneous warning regarding the use of obsolete PlatformIO Fixed when downgrading to the stable version (`issue #4664 `_) * Updated the `pio project metadata `__ command to return C/C++ flags as parsed Unix shell arguments when dumping project build metadata * Resolved a critical issue related to the usage of the ``-include`` flag within the `build_flags `__ option, specifically when employing dynamic variables (`issue #4682 `_) * Removed PlatformIO IDE for Atom from the documentation as `Atom has been deprecated `__ @@ -148,7 +148,7 @@ test-driven methodologies, and modern toolchains for unrivaled success. * Resolved an issue where native tests would fail if a custom program name was specified (`issue #4546 `_) * Resolved an issue where the PlatformIO |DEBUGGING| solution was not escaping the tool installation process into MI2 correctly (`issue #4565 `_) * Resolved an issue where multiple targets were not executed sequentially (`issue #4604 `_) -* Resolved an issue where upgrading PlatformIO Core fails on Windows with Python 3.11 (`issue #4540 `_) +* Resolved an issue where upgrading PlatformIO Fixed fails on Windows with Python 3.11 (`issue #4540 `_) 6.1.6 (2023-01-23) ~~~~~~~~~~~~~~~~~~ @@ -167,7 +167,7 @@ test-driven methodologies, and modern toolchains for unrivaled success. ~~~~~~~~~~~~~~~~~~ * Added a new `enable_proxy_strict_ssl `__ setting to disable the proxy server certificate verification (`issue #4432 `_) -* Documented `PlatformIO Core Proxy Configuration `__ +* Documented `PlatformIO Fixed Proxy Configuration `__ * Speeded up device port finder by avoiding loading board HWIDs from development platforms * Improved caching of build metadata in debug mode * Fixed an issue when `pio pkg install --storage-dir `__ command requires PlatformIO project (`issue #4410 `_) @@ -270,7 +270,7 @@ test-driven methodologies, and modern toolchains for unrivaled success. 6.0.1 (2022-05-17) ~~~~~~~~~~~~~~~~~~ -* Improved support for the renamed configuration options (`issue #4270 `_) +* Improved support for the renamed configuration options (`issue #4270 `_) * Fixed an issue when calling the built-in `pio device monitor `__ filters * Fixed an issue when using |INTERPOLATION| and merging str+int options (`issue #4271 `_) @@ -368,34 +368,34 @@ Please check the `Migration guide from 5.x to 6.0 `__. +See `PlatformIO Fixed 5.0 history `__. .. _release_notes_4: -PlatformIO Core 4 +PlatformIO Fixed 4 ----------------- -See `PlatformIO Core 4.0 history `__. +See `PlatformIO Fixed 4.0 history `__. -PlatformIO Core 3 +PlatformIO Fixed 3 ----------------- -See `PlatformIO Core 3.0 history `__. +See `PlatformIO Fixed 3.0 history `__. -PlatformIO Core 2 +PlatformIO Fixed 2 ----------------- -See `PlatformIO Core 2.0 history `__. +See `PlatformIO Fixed 2.0 history `__. -PlatformIO Core 1 +PlatformIO Fixed 1 ----------------- -See `PlatformIO Core 1.0 history `__. +See `PlatformIO Fixed 1.0 history `__. -PlatformIO Core Preview +PlatformIO Fixed Preview ----------------------- -See `PlatformIO Core Preview history `__. +See `PlatformIO Fixed Preview history `__. diff --git a/Makefile b/Makefile index d1f56e82e0..1e2e74de5a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ lint: - pylint --rcfile=./.pylintrc ./tests - pylint --rcfile=./.pylintrc ./platformio + ruff check ./tests + ruff check ./platformio isort: isort ./platformio diff --git a/README.rst b/README.rst index df73525eab..c48aec5ff4 100644 --- a/README.rst +++ b/README.rst @@ -1,9 +1,9 @@ -PlatformIO Core -=============== +PlatformIO Fixed +================ .. image:: https://github.com/platformio/platformio-core/workflows/Core/badge.svg :target: https://docs.platformio.org/en/latest/core/index.html - :alt: CI Build for PlatformIO Core + :alt: CI Build for PlatformIO Fixed .. image:: https://github.com/platformio/platformio-core/workflows/Docs/badge.svg :target: https://docs.platformio.org?utm_source=github&utm_medium=core :alt: CI Build for Docs @@ -85,7 +85,7 @@ See `contributing guidelines `_ diff --git a/SECURITY.md b/SECURITY.md index 3d71c1ec2a..a87848d892 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,8 +10,8 @@ To this end, we support only the following versions: | 6.1.x | :white_check_mark: | | < 6.1 | :x: | -Unsupported versions of the PlatformIO Core may have known vulnerabilities or security issues that could compromise the security of our organization's systems and data. -Therefore, it is important that all developers use only supported versions of the PlatformIO Core. +Unsupported versions of the PlatformIO Fixed may have known vulnerabilities or security issues that could compromise the security of our organization's systems and data. +Therefore, it is important that all developers use only supported versions of the PlatformIO Fixed. ## Reporting a Vulnerability diff --git a/action_items_types.md b/action_items_types.md new file mode 100644 index 0000000000..c0701d750b --- /dev/null +++ b/action_items_types.md @@ -0,0 +1,311 @@ +# Action Items: Adding Return Types to Python Files + +This document outlines the plan for systematically adding return type hints to functions and methods across the `platformio-core` codebase. + +## General Strategy + +1. **Prioritization**: Start with core modules and frequently modified files to maximize impact. +2. **Incremental Changes**: Implement type hints file by file, or even function by function within a file, to allow for manageable pull requests and easier review. +3. **Leverage Type Checkers**: Utilize `mypy` or similar type checkers to validate changes and identify missing or incorrect type hints. +4. **Consult Documentation**: Refer to Python's typing documentation and existing type-hinted code within the project for best practices. +5. **Consider Stub Files**: For complex cases or third-party libraries without type hints, consider creating `.pyi` stub files. +6. **Testing**: Ensure that existing tests pass after adding type hints. New tests should also include type hints. + +## Files Requiring Return Type Annotations + +The following Python files have been identified as needing return type annotations: + +- /c/Users/niteris/dev/platformio-core/platformio/compat.py +- /c/Users/niteris/dev/platformio-core/platformio/check/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/commands/lib.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/publish.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/config/base.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/process/base.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/piotarget.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/piolib.py +- /c/Users/niteris/dev/platformio-core/platformio/device/finder.py +- /c/Users/niteris/dev/platformio-core/platformio/commands/ci.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/exec.py +- /c/Users/niteris/dev/platformio-core/platformio/fs.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/project.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manifest/parser.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/library.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/outdated.py +- /c/Users/niteris/dev/platformio-core/platformio/project/config.py +- /c/Users/niteris/dev/platformio-core/platformio/package/unpack.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/process/client.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/piobuild.py +- /c/Users/niteris/dev/platformio-core/platformio/commands/upgrade.py +- /c/Users/niteris/dev/platformio-core/platformio/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/commands/device/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/test/runners/readers/native.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/client/base.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/piocore.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/pioplatform.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/main.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/pioino.py +- /c/Users/niteris/dev/platformio-core/platformio/app.py +- /c/Users/niteris/dev/platformio-core/platformio/account/client.py +- /c/Users/niteris/dev/platformio-core/platformio/__main__.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/piointegration.py +- /c/Users/niteris/dev/platformio-core/platformio/check/tools/base.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/piomisc.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manifest/schema.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/core.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/server.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/piosize.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/pioupload.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/ac/process.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/ac/serial.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/ac/base.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/client/agent_service.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/piomaxlen.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/pioasm.py +- /c/Users/niteris/dev/platformio-core/platformio/check/defect.py +- /c/Users/niteris/dev/platformio-core/platformio/commands/platform.py +- /c/Users/niteris/dev/platformio-core/platformio/check/tools/pvsstudio.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/misc.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/helpers.py +- /c/Users/niteris/dev/platformio-core/platformio/device/monitor/filters/base.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/config/blackmagic.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/process/gdb.py +- /c/Users/niteris/dev/platformio-core/platformio/device/list/util.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/ide.py +- /c/Users/niteris/dev/platformio-core/platformio/check/tools/clangtidy.py +- /c/Users/niteris/dev/platformio-core/platformio/check/tools/cppcheck.py +- /c/Users/niteris/dev/platformio-core/platformio/device/monitor/filters/log2file.py +- /c/Users/niteris/dev/platformio-core/platformio/device/monitor/filters/hexlify.py +- /c/Users/niteris/dev/platformio-core/platformio/device/monitor/filters/send_on_enter.py +- /c/Users/niteris/dev/platformio-core/platformio/device/monitor/filters/time.py +- /c/Users/niteris/dev/platformio-core/platformio/device/monitor/terminal.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/app.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/os.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/platform.py +- /c/Users/niteris/dev/platformio-core/platformio/package/download.py +- /c/Users/niteris/dev/platformio-core/platformio/home/run.py +- /c/Users/niteris/dev/platformio-core/platformio/http.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/install.py +- /c/Users/niteris/dev/platformio-core/platformio/maintenance.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/show.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/unpublish.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/base.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/_download.py +- /c/Users/niteris/dev/platformio-core/platformio/package/lockfile.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/_install.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/_registry.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/_legacy.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/_uninstall.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/_symlink.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/_update.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/platform.py +- /c/Users/niteris/dev/platformio-core/platformio/package/meta.py +- /c/Users/niteris/dev/platformio-core/platformio/platform/_run.py +- /c/Users/niteris/dev/platformio-core/platformio/package/pack.py +- /c/Users/niteris/dev/platformio-core/platformio/platform/_packages.py +- /c/Users/niteris/dev/platformio-core/platformio/package/vcsclient.py +- /c/Users/niteris/dev/platformio-core/platformio/platform/factory.py +- /c/Users/niteris/dev/platformio-core/platformio/project/commands/metadata.py +- /c/Users/niteris/dev/platformio-core/platformio/proc.py +- /c/Users/niteris/dev/platformio-core/platformio/project/helpers.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/client.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/client/agent_list.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/ac/psync.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/client/device_list.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/client/async_base.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/factory/client.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/client/device_monitor.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/projectsync.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/client/run_or_test.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/client/update_core.py +- /c/Users/niteris/dev/platformio-core/platformio/telemetry.py +- /c/Users/niteris/dev/platformio-core/platformio/system/commands/info.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/factory/ssl.py +- /c/Users/niteris/dev/platformio-core/platformio/run/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/util.py +- /c/Users/niteris/dev/platformio-core/platformio/system/completion.py +- /c/Users/niteris/dev/platformio-core/platformio/test/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/test/runners/doctest.py +- /c/Users/niteris/dev/platformio-core/platformio/test/runners/base.py +- /c/Users/niteris/dev/platformio-core/platformio/test/runners/factory.py +- /c/Users/niteris/dev/platformio-core/platformio/test/runners/unity.py +- /c/Users/niteris/dev/platformio-core/platformio/test/runners/googletest.py +- /c/Users/niteris/dev/platformio-core/platformio/test/runners/readers/serial.py +- /c/Users/niteris/dev/platformio-core/setup.py +- /c/Users/niteris/dev/platformio-core/platformio/__init__.py +- /c/Users/niteris/dev/platformio-core/tests/package/test_manifest.py +- /c/Users/niteris/dev/platformio-core/tests/package/test_manager.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_lib_complex.py +- /c/Users/niteris/dev/platformio-core/platformio/platform/board.py +- /c/Users/niteris/dev/platformio-core/tests/package/test_pack.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_platform.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_init.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_boards.py +- /c/Users/niteris/dev/platformio-core/platformio/platform/base.py +- /c/Users/niteris/dev/platformio-core/tests/commands/pkg/test_exec.py +- /c/Users/niteris/dev/platformio-core/scripts/docspregen.py +- /c/Users/niteris/dev/platformio-core/platformio/test/reports/json.py +- /c/Users/niteris/dev/platformio-core/platformio/test/helpers.py +- /c/Users/niteris/dev/platformio-core/platformio/run/processor.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/mirror.py +- /c/Users/niteris/dev/platformio-core/platformio/project/options.py +- /c/Users/niteris/dev/platformio-core/platformio/project/commands/init.py +- /c/Users/niteris/dev/platformio-core/scripts/fixsymlink.py +- /c/Users/niteris/dev/platformio-core/platformio/cache.py +- /c/Users/niteris/dev/platformio-core/platformio/public.py +- /c/Users/niteris/dev/platformio-core/tests/test_examples.py +- /c/Users/niteris/dev/platformio-core/tests/project/test_savedeps.py +- /c/Users/niteris/dev/platformio-core/tests/project/test_metadata.py +- /c/Users/niteris/dev/platformio-core/tests/project/test_config.py +- /c/Users/niteris/dev/platformio-core/tests/package/test_meta.py +- /c/Users/niteris/dev/platformio-core/tests/project/__init__.py +- /c/Users/niteris/dev/platformio-core/tests/package/__init__.py +- /c/Users/niteris/dev/platformio-core/tests/misc/test_misc.py +- /c/Users/niteris/dev/platformio-core/tests/misc/test_maintenance.py +- /c/Users/niteris/dev/platformio-core/tests/misc/ino2cpp/test_ino2cpp.py +- /c/Users/niteris/dev/platformio-core/tests/misc/__init__.py +- /c/Users/niteris/dev/platformio-core/tests/misc/ino2cpp/__init__.py +- /c/Users/niteris/dev/platformio-core/tests/conftest.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_test.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_settings.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_run.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_lib.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_ci.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_check.py +- /c/Users/niteris/dev/platformio-core/tests/commands/test_account_org_team.py +- /c/Users/niteris/dev/platformio-core/tests/commands/pkg/test_update.py +- /c/Users/niteris/dev/platformio-core/tests/commands/pkg/test_uninstall.py +- /c/Users/niteris/dev/platformio-core/tests/commands/pkg/test_show.py +- /c/Users/niteris/dev/platformio-core/tests/commands/pkg/test_search.py +- /c/Users/niteris/dev/platformio-core/tests/commands/pkg/test_outdated.py +- /c/Users/niteris/dev/platformio-core/tests/commands/pkg/test_list.py +- /c/Users/niteris/dev/platformio-core/tests/commands/pkg/test_install.py +- /c/Users/niteris/dev/platformio-core/tests/commands/pkg/__init__.py +- /c/Users/niteris/dev/platformio-core/tests/__init__.py +- /c/Users/niteris/dev/platformio-core/tests/commands/__init__.py +- /c/Users/niteris/dev/platformio-core/scripts/install_devplatforms.py +- /c/Users/niteris/dev/platformio-core/platformio/test/runners/readers/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/test/result.py +- /c/Users/niteris/dev/platformio-core/platformio/test/runners/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/test/reports/stdout.py +- /c/Users/niteris/dev/platformio-core/platformio/test/reports/junit.py +- /c/Users/niteris/dev/platformio-core/platformio/test/reports/base.py +- /c/Users/niteris/dev/platformio-core/platformio/test/reports/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/test/exception.py +- /c/Users/niteris/dev/platformio-core/platformio/test/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/system/prune.py +- /c/Users/niteris/dev/platformio-core/platformio/system/commands/prune.py +- /c/Users/niteris/dev/platformio-core/platformio/system/commands/completion.py +- /c/Users/niteris/dev/platformio-core/platformio/system/commands/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/system/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/system/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/run/helpers.py +- /c/Users/niteris/dev/platformio-core/platformio/run/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/factory/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/client/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/remote/ac/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/access/validate.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/access/commands/public.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/access/commands/revoke.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/access/commands/private.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/access/commands/list.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/access/commands/grant.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/access/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/access/commands/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/registry/access/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/project/savedeps.py +- /c/Users/niteris/dev/platformio-core/platformio/project/integration/generator.py +- /c/Users/niteris/dev/platformio-core/platformio/project/integration/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/project/exception.py +- /c/Users/niteris/dev/platformio-core/platformio/project/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/project/commands/config.py +- /c/Users/niteris/dev/platformio-core/platformio/project/commands/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/project/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/platform/exception.py +- /c/Users/niteris/dev/platformio-core/platformio/platform/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/package/version.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manifest/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/tool.py +- /c/Users/niteris/dev/platformio-core/platformio/package/manager/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/package/exception.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/update.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/uninstall.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/search.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/pack.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/list.py +- /c/Users/niteris/dev/platformio-core/platformio/package/commands/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/package/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/package/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/registry.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/base.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/account.py +- /c/Users/niteris/dev/platformio-core/platformio/home/rpc/handlers/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/home/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/home/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/exception.py +- /c/Users/niteris/dev/platformio-core/platformio/device/monitor/filters/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/device/monitor/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/device/monitor/command.py +- /c/Users/niteris/dev/platformio-core/platformio/device/list/command.py +- /c/Users/niteris/dev/platformio-core/platformio/device/list/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/device/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/dependencies.py +- /c/Users/niteris/dev/platformio-core/platformio/device/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/process/server.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/process/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/exception.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/config/qemu.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/config/renode.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/config/native.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/config/mspdebug.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/config/jlink.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/config/generic.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/config/factory.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/config/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/debug/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/commands/update.py +- /c/Users/niteris/dev/platformio-core/platformio/commands/settings.py +- /c/Users/niteris/dev/platformio-core/platformio/commands/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/commands/boards.py +- /c/Users/niteris/dev/platformio-core/platformio/check/tools/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/check/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/piotest.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/pioproject.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/piohooks.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/builder/tools/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/account/validate.py +- /c/Users/niteris/dev/platformio-core/platformio/account/team/commands/update.py +- /c/Users/niteris/dev/platformio-core/platformio/account/team/commands/remove.py +- /c/Users/niteris/dev/platformio-core/platformio/account/team/commands/list.py +- /c/Users/niteris/dev/platformio-core/platformio/account/team/commands/destroy.py +- /c/Users/niteris/dev/platformio-core/platformio/account/team/commands/create.py +- /c/Users/niteris/dev/platformio-core/platformio/account/team/commands/add.py +- /c/Users/niteris/dev/platformio-core/platformio/account/team/commands/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/account/team/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/account/team/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/account/org/commands/update.py +- /c/Users/niteris/dev/platformio-core/platformio/account/org/commands/list.py +- /c/Users/niteris/dev/platformio-core/platformio/account/org/commands/remove.py +- /c/Users/niteris/dev/platformio-core/platformio/account/org/commands/destroy.py +- /c/Users/niteris/dev/platformio-core/platformio/account/org/commands/add.py +- /c/Users/niteris/dev/platformio-core/platformio/account/org/commands/create.py +- /c/Users/niteris/dev/platformio-core/platformio/account/org/commands/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/account/org/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/account/org/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/account/commands/update.py +- /c/Users/niteris/dev/platformio-core/platformio/account/commands/token.py +- /c/Users/niteris/dev/platformio-core/platformio/account/commands/show.py +- /c/Users/niteris/dev/platformio-core/platformio/account/commands/register.py +- /c/Users/niteris/dev/platformio-core/platformio/account/commands/password.py +- /c/Users/niteris/dev/platformio-core/platformio/account/commands/logout.py +- /c/Users/niteris/dev/platformio-core/platformio/account/commands/login.py +- /c/Users/niteris/dev/platformio-core/platformio/account/commands/forgot.py +- /c/Users/niteris/dev/platformio-core/platformio/account/commands/destroy.py +- /c/Users/niteris/dev/platformio-core/platformio/account/commands/__init__.py +- /c/Users/niteris/dev/platformio-core/platformio/account/cli.py +- /c/Users/niteris/dev/platformio-core/platformio/account/__init__.py diff --git a/clean b/clean new file mode 100644 index 0000000000..e8b1fae263 --- /dev/null +++ b/clean @@ -0,0 +1,26 @@ +#!/bin/bash + +# This script cleans the project directory of temporary and build files. + +set -e + +echo "Cleaning project..." + +# Remove virtual environment +rm -rf .venv + +# Remove build artifacts +rm -rf build/ +rm -rf dist/ +rm -rf .tox/ +rm -rf *.egg-info/ +rm -rf platformio.egg-info/ + +# Remove pytest cache +rm -rf .pytest_cache/ + +# Remove pycache directories and pyc files +find . -type d -name "__pycache__" -exec rm -rf {} + +find . -type f -name "*.pyc" -delete + +echo "Clean complete." diff --git a/install b/install new file mode 100644 index 0000000000..b8dabe0fb9 --- /dev/null +++ b/install @@ -0,0 +1,17 @@ +#!/bin/bash + +# This script installs the project and its dependencies using uv. + +# Exit immediately if a command exits with a non-zero status. +set -e + +# Check if uv is installed, and install it if not +if ! command -v uv &> /dev/null +then + echo "uv not found, installing..." + curl -LsSf https://astral.sh/uv/install.sh | sh +fi + +# Install the project in editable mode with the dev dependencies. +# $HOME/.local/bin/uv pip install -e .[dev] +uv pip install -e .[dev] \ No newline at end of file diff --git a/lint b/lint new file mode 100644 index 0000000000..afc6a1ca5b --- /dev/null +++ b/lint @@ -0,0 +1,11 @@ + +#!/bin/bash + +# This script runs the linters on the project. + +# Run the linters. +uv run ruff check --fix platformio + +uv run isort platformio + +uv run pyright platformio diff --git a/platformio/__init__.py b/platformio/__init__.py index 732424fa2d..cf4c24f573 100644 --- a/platformio/__init__.py +++ b/platformio/__init__.py @@ -15,7 +15,7 @@ VERSION = (6, 1, "19a2") __version__ = ".".join([str(s) for s in VERSION]) -__title__ = "platformio" +__title__ = "platformio-fixed" __description__ = ( "Your Gateway to Embedded Software Development Excellence. " "Unlock the true potential of embedded software development " diff --git a/platformio/__main__.py b/platformio/__main__.py index 58cabe8b66..65149811c2 100644 --- a/platformio/__main__.py +++ b/platformio/__main__.py @@ -24,9 +24,9 @@ @click.command( - cls=PlatformioCLI, context_settings=dict(help_option_names=["-h", "--help"]) + cls=PlatformioCLI, context_settings={"help_option_names": ["-h", "--help"]} ) -@click.version_option(__version__, prog_name="PlatformIO Core") +@click.version_option(__version__, prog_name="PlatformIO Fixed") @click.option("--force", "-f", is_flag=True, help="DEPRECATED", hidden=True) @click.option("--caller", "-c", help="Caller ID (service)") @click.option("--no-ansi", is_flag=True, help="Do not print ANSI control characters") @@ -41,7 +41,7 @@ def cli(ctx, force, caller, no_ansi): # pylint: disable=unused-argument == "true" ): # pylint: disable=protected-access - click._compat.isatty = lambda stream: False + click._compat.isatty = lambda stream: False # type: ignore elif ( str( os.getenv("PLATFORMIO_FORCE_ANSI", os.getenv("PLATFORMIO_FORCE_COLOR")) @@ -49,8 +49,8 @@ def cli(ctx, force, caller, no_ansi): # pylint: disable=unused-argument == "true" ): # pylint: disable=protected-access - click._compat.isatty = lambda stream: True - except: # pylint: disable=bare-except + click._compat.isatty = lambda stream: True # type: ignore + except Exception: # pylint: disable=bare-except pass maintenance.on_cmd_start(ctx, caller) @@ -124,7 +124,7 @@ def main(argv=None): https://docs.platformio.org/page/faq/index.html * Report this problem to the developers - https://github.com/platformio/platformio-core/issues + https://github.com/platformio/platformio-fixed/issues ============================================================ """ diff --git a/platformio/account/client.py b/platformio/account/client.py index 3079c7ca5d..8fe0d07fcc 100644 --- a/platformio/account/client.py +++ b/platformio/account/client.py @@ -88,7 +88,7 @@ def fetch_authentication_token(self): def login(self, username, password): try: self.fetch_authentication_token() - except: # pylint:disable=bare-except + except Exception: # pylint:disable=bare-except pass else: raise AccountAlreadyAuthorized( @@ -106,7 +106,7 @@ def login(self, username, password): def login_with_code(self, client_id, code, redirect_uri): try: self.fetch_authentication_token() - except: # pylint:disable=bare-except + except Exception: # pylint:disable=bare-except pass else: raise AccountAlreadyAuthorized( @@ -147,7 +147,7 @@ def registration( ): # pylint: disable=too-many-arguments,too-many-positional-arguments try: self.fetch_authentication_token() - except: # pylint:disable=bare-except + except Exception: # pylint:disable=bare-except pass else: raise AccountAlreadyAuthorized( @@ -218,18 +218,18 @@ def get_account_info(self, offline=False): "/v1/summary", x_with_authorization=True, ) - account["summary"] = dict( - profile=result.get("profile"), - packages=result.get("packages"), - subscriptions=result.get("subscriptions"), - user_id=result.get("user_id"), - expire_at=int(time.time()) + self.SUMMARY_CACHE_TTL, - ) + account["summary"] = { + "profile": result.get("profile"), + "packages": result.get("packages"), + "subscriptions": result.get("subscriptions"), + "user_id": result.get("user_id"), + "expire_at": int(time.time()) + self.SUMMARY_CACHE_TTL, + } app.set_state_item("account", account) return result def get_logged_username(self): - return self.get_account_info(offline=True).get("profile").get("username") + return self.get_account_info(offline=True).get("profile").get("username") # type: ignore def destroy_account(self): return self.fetch_json_data( diff --git a/platformio/app.py b/platformio/app.py index 7d2f1ea9b7..b59bf243c0 100644 --- a/platformio/app.py +++ b/platformio/app.py @@ -93,7 +93,7 @@ def __init__(self, path=None, lock=False): def __enter__(self): try: self._lock_state_file() - if os.path.isfile(self.path): + if os.path.isfile(self.path): # type: ignore self._storage = fs.load_json(self.path) assert isinstance(self._storage, dict) except ( @@ -108,11 +108,11 @@ def __enter__(self): def __exit__(self, type_, value, traceback): if self.modified: try: - with open(self.path, mode="w", encoding="utf8") as fp: + with open(self.path, mode="w", encoding="utf8") as fp: # type: ignore fp.write(json.dumps(self._storage)) except IOError as exc: raise exception.HomeDirPermissionsError( - os.path.dirname(self.path) + os.path.dirname(self.path) # type: ignore ) from exc self._unlock_state_file() @@ -123,7 +123,7 @@ def _lock_state_file(self): try: self._lockfile.acquire() except IOError as exc: - raise exception.HomeDirPermissionsError(os.path.dirname(self.path)) from exc + raise exception.HomeDirPermissionsError(os.path.dirname(self.path)) from exc # type: ignore def _unlock_state_file(self): if hasattr(self, "_lockfile") and self._lockfile: @@ -185,7 +185,7 @@ def sanitize_setting(name, value): def get_state_item(name, default=None): with State() as state: - return state.get(name, default) + return state.get(name, default) # type: ignore def set_state_item(name, value): @@ -250,9 +250,9 @@ def get_cid(): uid = os.getenv("GITPOD_GIT_USER_NAME") if not uid: uid = uuid.getnode() - cid = uuid.UUID(bytes=hashlib.md5(hashlib_encode_data(uid)).digest()) + cid = uuid.UUID(bytes=hashlib.md5(hashlib_encode_data(uid)).digest()) # type: ignore cid = str(cid) - if IS_WINDOWS or os.getuid() > 0: # pylint: disable=no-member + if IS_WINDOWS or os.getuid() > 0: # type: ignore set_state_item("cid", cid) set_state_item("created_at", int(time.time())) return cid @@ -280,11 +280,11 @@ def get_user_agent(): def get_host_id(): - h = hashlib.sha1(hashlib_encode_data(get_cid())) + h = hashlib.sha1(hashlib_encode_data(get_cid())) # type: ignore try: username = getpass.getuser() - h.update(hashlib_encode_data(username)) - except: # pylint: disable=bare-except + h.update(hashlib_encode_data(username)) # type: ignore + except Exception: # pylint: disable=bare-except pass return h.hexdigest() diff --git a/platformio/builder/main.py b/platformio/builder/main.py index 880ca155ac..857e3b0795 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -18,15 +18,17 @@ from time import time import click -from SCons.Script import ARGUMENTS # pylint: disable=import-error -from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error -from SCons.Script import DEFAULT_TARGETS # pylint: disable=import-error -from SCons.Script import AllowSubstExceptions # pylint: disable=import-error -from SCons.Script import AlwaysBuild # pylint: disable=import-error -from SCons.Script import Default # pylint: disable=import-error -from SCons.Script import DefaultEnvironment # pylint: disable=import-error -from SCons.Script import Import # pylint: disable=import-error -from SCons.Script import Variables # pylint: disable=import-error +from SCons.Script import ( # type: ignore + ARGUMENTS, + COMMAND_LINE_TARGETS, + DEFAULT_TARGETS, + AllowSubstExceptions, + AlwaysBuild, + Default, + DefaultEnvironment, + Import, + Variables, +) from platformio import app, fs from platformio.platform.base import PlatformBase @@ -46,8 +48,8 @@ ("PROGRAM_ARGS",), ) -DEFAULT_ENV_OPTIONS = dict( - tools=[ +DEFAULT_ENV_OPTIONS = { + "tools": [ "ar", "cc", "c++", @@ -67,32 +69,32 @@ "piointegration", "piomaxlen", ], - toolpath=[os.path.join(fs.get_source_dir(), "builder", "tools")], - variables=clivars, + "toolpath": [os.path.join(fs.get_source_dir(), "builder", "tools")], + "variables": clivars, # Propagating External Environment - ENV=os.environ, - UNIX_TIME=int(time()), - BUILD_DIR=os.path.join("$PROJECT_BUILD_DIR", "$PIOENV"), - BUILD_SRC_DIR=os.path.join("$BUILD_DIR", "src"), - BUILD_TEST_DIR=os.path.join("$BUILD_DIR", "test"), - COMPILATIONDB_PATH=os.path.join("$PROJECT_DIR", "compile_commands.json"), - LIBPATH=["$BUILD_DIR"], - PROGNAME="program", - PROGPATH=os.path.join("$BUILD_DIR", "$PROGNAME$PROGSUFFIX"), - PROG_PATH="$PROGPATH", # deprecated - PYTHONEXE=get_pythonexe_path(), -) + "ENV": os.environ, + "UNIX_TIME": int(time()), + "BUILD_DIR": os.path.join("$PROJECT_BUILD_DIR", "$PIOENV"), + "BUILD_SRC_DIR": os.path.join("$BUILD_DIR", "src"), + "BUILD_TEST_DIR": os.path.join("$BUILD_DIR", "test"), + "COMPILATIONDB_PATH": os.path.join("$PROJECT_DIR", "compile_commands.json"), + "LIBPATH": ["$BUILD_DIR"], + "PROGNAME": "program", + "PROGPATH": os.path.join("$BUILD_DIR", "$PROGNAME$PROGSUFFIX"), + "PROG_PATH": "$PROGPATH", # deprecated + "PYTHONEXE": get_pythonexe_path(), +} # Declare command verbose messages -command_strings = dict( - ARCOM="Archiving", - LINKCOM="Linking", - RANLIBCOM="Indexing", - ASCOM="Compiling", - ASPPCOM="Compiling", - CCCOM="Compiling", - CXXCOM="Compiling", -) +command_strings = { + "ARCOM": "Archiving", + "LINKCOM": "Linking", + "RANLIBCOM": "Indexing", + "ASCOM": "Compiling", + "ASPPCOM": "Compiling", + "CCCOM": "Compiling", + "CXXCOM": "Compiling", +} if not int(ARGUMENTS.get("PIOVERBOSE", 0)): for name, value in command_strings.items(): DEFAULT_ENV_OPTIONS["%sSTR" % name] = "%s $TARGET" % (value) @@ -137,7 +139,7 @@ if int(ARGUMENTS.get("ISATTY", 0)): # pylint: disable=protected-access - click._compat.isatty = lambda stream: True + click._compat.isatty = lambda stream: True # type: ignore if env.subst("$BUILD_CACHE_DIR"): if not os.path.isdir(env.subst("$BUILD_CACHE_DIR")): @@ -182,9 +184,7 @@ ############################################################################## # Checking program size -if env.get("SIZETOOL") and not ( - set(["nobuild", "sizedata"]) & set(COMMAND_LINE_TARGETS) -): +if env.get("SIZETOOL") and not ( {"nobuild", "sizedata"} & set(COMMAND_LINE_TARGETS)): env.Depends("upload", "checkprogsize") # Replace platform's "size" target with our _new_targets = [t for t in DEFAULT_TARGETS if str(t) != "size"] @@ -219,12 +219,12 @@ projenv = None try: Import("projenv") - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except projenv = env - data = projenv.DumpIntegrationData(env) + data = projenv.DumpIntegrationData(env) # type: ignore # dump to file for the further reading by project.helpers.load_build_metadata with open( - projenv.subst(os.path.join("$BUILD_DIR", "idedata.json")), + projenv.subst(os.path.join("$BUILD_DIR", "idedata.json")), # type: ignore mode="w", encoding="utf8", ) as fp: diff --git a/platformio/builder/tools/pioasm.py b/platformio/builder/tools/pioasm.py index 4d5cfc13d2..b75e6e32f2 100644 --- a/platformio/builder/tools/pioasm.py +++ b/platformio/builder/tools/pioasm.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import SCons.Tool.asm # pylint: disable=import-error +import SCons.Tool.asm # type: ignore # # Resolve https://github.com/platformio/platformio-core/issues/3917 diff --git a/platformio/builder/tools/piobuild.py b/platformio/builder/tools/piobuild.py index 8ef2522cf7..565464d7fb 100644 --- a/platformio/builder/tools/piobuild.py +++ b/platformio/builder/tools/piobuild.py @@ -16,12 +16,14 @@ import os import sys -from SCons import Builder, Util # pylint: disable=import-error -from SCons.Node import FS # pylint: disable=import-error -from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error -from SCons.Script import AlwaysBuild # pylint: disable=import-error -from SCons.Script import DefaultEnvironment # pylint: disable=import-error -from SCons.Script import SConscript # pylint: disable=import-error +from SCons import Builder, Util # type: ignore +from SCons.Node import FS # type: ignore +from SCons.Script import ( # type: ignore + COMMAND_LINE_TARGETS, + AlwaysBuild, + DefaultEnvironment, + SConscript, +) from platformio import __version__, fs from platformio.compat import IS_MACOS, string_types @@ -46,11 +48,7 @@ def scons_patched_match_splitext(path, suffixes=None): def GetBuildType(env): modes = [] - if ( - set(["__debug", "sizedata"]) # sizedata = for memory inspection - & set(COMMAND_LINE_TARGETS) - or env.GetProjectOption("build_type") == "debug" - ): + if {"__debug", "sizedata"} & set(COMMAND_LINE_TARGETS) or env.GetProjectOption("build_type") == "debug": modes.append("debug") if "__test" in COMMAND_LINE_TARGETS or env.GetProjectOption("build_type") == "test": modes.append("test") @@ -221,9 +219,9 @@ def ParseFlagsExtended(env, flags): # pylint: disable=too-many-branches result[k][i] = os.path.abspath(p) # fix relative LIBs - for i, l in enumerate(result.get("LIBS", [])): - if isinstance(l, FS.File): - result["LIBS"][i] = os.path.abspath(l.get_path()) + for i, _l in enumerate(result.get("LIBS", [])): + if isinstance(_l, FS.File): + result["LIBS"][i] = os.path.abspath(_l.get_path()) # fix relative path for "-include" for i, f in enumerate(result.get("CCFLAGS", [])): diff --git a/platformio/builder/tools/pioino.py b/platformio/builder/tools/pioino.py index c44e72b74f..cf914b7979 100644 --- a/platformio/builder/tools/pioino.py +++ b/platformio/builder/tools/pioino.py @@ -102,7 +102,7 @@ def merge(self, nodes): return "\n".join(["#include "] + lines) if lines else None def process(self, contents): - out_file = re.sub(r"[\"\'\;]+", "", self._main_ino) + ".cpp" + out_file = re.sub(r"[\"\'\;]+", "", self._main_ino) + ".cpp" # type: ignore assert self._gcc_preprocess(contents, out_file) contents = self.read_safe_contents(out_file) contents = self._join_multiline_strings(contents) @@ -148,7 +148,7 @@ def _join_multiline_strings(self, contents): newlines[len(newlines) - 1] += line stropen = False newlines.append( - '#line %d "%s"' % (linenum, self._main_ino.replace("\\", "/")) + '#line %d "%s"' % (linenum, self._main_ino.replace("\\", "/")) # type: ignore ) continue @@ -167,12 +167,9 @@ def _parse_preproc_line_num(line): def _parse_prototypes(self, contents): prototypes = [] - reserved_keywords = set(["if", "else", "while"]) + reserved_keywords = {"if", "else", "while"} for match in self.PROTOTYPE_RE.finditer(contents): - if ( - set([match.group(2).strip(), match.group(3).strip()]) - & reserved_keywords - ): + if ({match.group(2).strip(), match.group(3).strip()} & reserved_keywords): continue prototypes.append(match) return prototypes @@ -192,13 +189,13 @@ def append_prototypes(self, contents): prototypes = self._parse_prototypes(contents) or [] # skip already declared prototypes - declared = set(m.group(1).strip() for m in prototypes if m.group(4) == ";") + declared = {m.group(1).strip() for m in prototypes if m.group(4) == ";"} prototypes = [m for m in prototypes if m.group(1).strip() not in declared] if not prototypes: return contents - prototype_names = set(m.group(3).strip() for m in prototypes) + prototype_names = {m.group(3).strip() for m in prototypes} split_pos = prototypes[0].start() match_ptrs = re.search( self.PROTOPTRS_TPLRE % ("|".join(prototype_names)), @@ -215,7 +212,7 @@ def append_prototypes(self, contents): '#line %d "%s"' % ( self._get_total_lines(contents[:split_pos]), - self._main_ino.replace("\\", "/"), + self._main_ino.replace("\\", "/"), # type: ignore ) ) result.append(contents[split_pos:].strip()) @@ -243,7 +240,7 @@ def _delete_file(path): try: if os.path.isfile(path): os.remove(path) - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except pass diff --git a/platformio/builder/tools/piointegration.py b/platformio/builder/tools/piointegration.py index 00ecb88a09..8de9df003d 100644 --- a/platformio/builder/tools/piointegration.py +++ b/platformio/builder/tools/piointegration.py @@ -15,19 +15,19 @@ import glob import os -import SCons.Defaults # pylint: disable=import-error -import SCons.Subst # pylint: disable=import-error -from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error +import SCons.Defaults # type: ignore +import SCons.Subst # type: ignore +from SCons.Script import COMMAND_LINE_TARGETS # type: ignore from platformio.proc import exec_command, where_is_program def IsIntegrationDump(_): - return set(["__idedata", "idedata"]) & set(COMMAND_LINE_TARGETS) + return {"__idedata", "idedata"} & set(COMMAND_LINE_TARGETS) def DumpIntegrationIncludes(env): - result = dict(build=[], compatlib=[], toolchain=[]) + result = {"build": [], "compatlib": [], "toolchain": []} # `env`(project) CPPPATH result["build"].extend( @@ -70,8 +70,8 @@ def get_gcc_defines(env): return items if result["returncode"] != 0: return items - for line in result["out"].split("\n"): - tokens = line.strip().split(" ", 2) + for line in result["out"].split("\n"): # type: ignore + tokens = line.strip().split(" ", 2) # type: ignore if not tokens or tokens[0] != "#define": continue if len(tokens) > 2: @@ -163,12 +163,12 @@ def DumpIntegrationData(*args): "svd_path": dump_svd_path(globalenv), "compiler_type": globalenv.GetCompilerType(), "targets": globalenv.DumpTargets(), - "extra": dict( - flash_images=[ + "extra": { + "flash_images": [ {"offset": item[0], "path": globalenv.subst(item[1])} for item in globalenv.get("FLASH_EXTRA_IMAGES", []) ] - ), + }, } for key in ("IDE_EXTRA_DATA", "INTEGRATION_EXTRA_DATA"): data["extra"].update(globalenv.get(key, {})) diff --git a/platformio/builder/tools/piolib.py b/platformio/builder/tools/piolib.py index 36b72d2654..48adad6387 100644 --- a/platformio/builder/tools/piolib.py +++ b/platformio/builder/tools/piolib.py @@ -22,9 +22,8 @@ import sys import click -import SCons.Scanner # pylint: disable=import-error -from SCons.Script import ARGUMENTS # pylint: disable=import-error -from SCons.Script import DefaultEnvironment # pylint: disable=import-error +import SCons.Scanner # type: ignore +from SCons.Script import ARGUMENTS, DefaultEnvironment # type: ignore from platformio import exception, fs from platformio.builder.tools import piobuild @@ -45,7 +44,9 @@ class LibBuilderFactory: @staticmethod - def new(env, path, verbose=int(ARGUMENTS.get("PIOVERBOSE", 0))): + def new(env, path, verbose=None): + if verbose is None: + verbose = int(ARGUMENTS.get("PIOVERBOSE", 0)) clsname = "UnknownLibBuilder" if os.path.isfile(os.path.join(path, "library.json")): clsname = "PlatformIOLibBuilder" @@ -256,7 +257,7 @@ def lib_ldf_mode(self): @staticmethod def validate_ldf_mode(mode): - ldf_modes = ProjectOptions["env.lib_ldf_mode"].type.choices + ldf_modes = ProjectOptions["env.lib_ldf_mode"].type.choices # type: ignore if isinstance(mode, string_types): mode = mode.strip().lower() if mode in ldf_modes: @@ -273,7 +274,7 @@ def lib_compat_mode(self): @staticmethod def validate_compat_mode(mode): - compat_modes = ProjectOptions["env.lib_compat_mode"].type.choices + compat_modes = ProjectOptions["env.lib_compat_mode"].type.choices # type: ignore if isinstance(mode, string_types): mode = mode.strip().lower() if mode in compat_modes: @@ -560,8 +561,8 @@ def get_include_dirs(self): def src_filter(self): src_dir = os.path.join(self.path, "src") if os.path.isdir(src_dir): - # pylint: disable=no-member - src_filter = LibBuilderBase.src_filter.fget(self) + # type: ignore + src_filter = LibBuilderBase.src_filter.fget(self) # type: ignore for root, _, files in os.walk(src_dir, followlinks=True): found = False for fname in files: @@ -595,15 +596,15 @@ def dependencies(self): @property def lib_ldf_mode(self): - # pylint: disable=no-member + # type: ignore if not self._manifest.get("dependencies"): - return LibBuilderBase.lib_ldf_mode.fget(self) + return LibBuilderBase.lib_ldf_mode.fget(self) # type: ignore missing = object() global_value = self.env.GetProjectConfig().getraw( "env:" + self.env["PIOENV"], "lib_ldf_mode", missing ) if global_value != missing: - return LibBuilderBase.lib_ldf_mode.fget(self) + return LibBuilderBase.lib_ldf_mode.fget(self) # type: ignore # automatically enable C++ Preprocessing in runtime # (Arduino IDE has this behavior) return "chain+" @@ -621,7 +622,7 @@ def is_platforms_compatible(self, platforms): @property def build_flags(self): ldflags = [ - LibBuilderBase.build_flags.fget(self), # pylint: disable=no-member + LibBuilderBase.build_flags.fget(self), # type: ignore self._manifest.get("ldflags"), ] if self._manifest.get("precompiled") in ("true", "full"): @@ -648,7 +649,7 @@ def load_manifest(self): def src_dir(self): if os.path.isdir(os.path.join(self.path, "source")): return os.path.join(self.path, "source") - return LibBuilderBase.src_dir.fget(self) # pylint: disable=no-member + return LibBuilderBase.src_dir.fget(self) # type: ignore def get_include_dirs(self): include_dirs = super().get_include_dirs() @@ -710,7 +711,7 @@ def _mbed_normalize_macro(macro): value = None if "=" in macro: name, value = macro.split("=", 1) - return dict(name=name, value=value) + return {"name": name, "value": value} def _mbed_lib_conf_parse_macros(self, mbed_lib_path): macros = {} @@ -726,9 +727,9 @@ def _mbed_lib_conf_parse_macros(self, mbed_lib_path): for key, options in manifest.get("config", {}).items(): if "value" not in options: continue - macros[key] = dict( - name=options.get("macro_name"), value=options.get("value") - ) + macros[key] = { + "name": options.get("macro_name"), "value": options.get("value") + } # overrode items per target for target, options in manifest.get("target_overrides", {}).items(): @@ -795,8 +796,8 @@ def _has_arduino_manifest(self): def include_dir(self): if "includeDir" in self._manifest.get("build", {}): with fs.cd(self.path): - return os.path.abspath(self._manifest.get("build").get("includeDir")) - return LibBuilderBase.include_dir.fget(self) # pylint: disable=no-member + return os.path.abspath(self._manifest.get("build").get("includeDir")) # type: ignore + return LibBuilderBase.include_dir.fget(self) # type: ignore def get_include_dirs(self): include_dirs = super().get_include_dirs() @@ -822,37 +823,37 @@ def get_include_dirs(self): def src_dir(self): if "srcDir" in self._manifest.get("build", {}): with fs.cd(self.path): - return os.path.abspath(self._manifest.get("build").get("srcDir")) - return LibBuilderBase.src_dir.fget(self) # pylint: disable=no-member + return os.path.abspath(self._manifest.get("build").get("srcDir")) # type: ignore + return LibBuilderBase.src_dir.fget(self) # type: ignore @property def src_filter(self): - # pylint: disable=no-member + # type: ignore if "srcFilter" in self._manifest.get("build", {}): - return self._manifest.get("build").get("srcFilter") + return self._manifest.get("build").get("srcFilter") # type: ignore if self.env["SRC_FILTER"]: return self.env["SRC_FILTER"] if self._has_arduino_manifest(): - return ArduinoLibBuilder.src_filter.fget(self) - return LibBuilderBase.src_filter.fget(self) + return ArduinoLibBuilder.src_filter.fget(self) # type: ignore + return LibBuilderBase.src_filter.fget(self) # type: ignore @property def build_flags(self): if "flags" in self._manifest.get("build", {}): - return self._manifest.get("build").get("flags") - return LibBuilderBase.build_flags.fget(self) # pylint: disable=no-member + return self._manifest.get("build").get("flags") # type: ignore + return LibBuilderBase.build_flags.fget(self) # type: ignore @property def build_unflags(self): if "unflags" in self._manifest.get("build", {}): - return self._manifest.get("build").get("unflags") - return LibBuilderBase.build_unflags.fget(self) # pylint: disable=no-member + return self._manifest.get("build").get("unflags") # type: ignore + return LibBuilderBase.build_unflags.fget(self) # type: ignore @property def extra_script(self): if "extraScript" in self._manifest.get("build", {}): - return self._manifest.get("build").get("extraScript") - return LibBuilderBase.extra_script.fget(self) # pylint: disable=no-member + return self._manifest.get("build").get("extraScript") # type: ignore + return LibBuilderBase.extra_script.fget(self) # type: ignore @property def lib_archive(self): @@ -864,26 +865,26 @@ def lib_archive(self): return self.env.GetProjectConfig().get( "env:" + self.env["PIOENV"], "lib_archive" ) - # pylint: disable=no-member + # type: ignore return self._manifest.get("build", {}).get( - "libArchive", LibBuilderBase.lib_archive.fget(self) + "libArchive", LibBuilderBase.lib_archive.fget(self) # type: ignore ) @property def lib_ldf_mode(self): - # pylint: disable=no-member + # type: ignore return self.validate_ldf_mode( self._manifest.get("build", {}).get( - "libLDFMode", LibBuilderBase.lib_ldf_mode.fget(self) + "libLDFMode", LibBuilderBase.lib_ldf_mode.fget(self) # type: ignore ) ) @property def lib_compat_mode(self): - # pylint: disable=no-member + # type: ignore return self.validate_compat_mode( self._manifest.get("build", {}).get( - "libCompatMode", LibBuilderBase.lib_compat_mode.fget(self) + "libCompatMode", LibBuilderBase.lib_compat_mode.fget(self) # type: ignore ) ) @@ -908,7 +909,7 @@ def __init__(self, env, *args, **kwargs): super().__init__(env, *args, **kwargs) self.env["SRC_FILTER"] = project_src_filter if export_projenv: - env.Export(dict(projenv=self.env)) + env.Export({"projenv": self.env}) def __contains__(self, child_path): for root_path in (self.include_dir, self.src_dir, self.test_dir): @@ -949,7 +950,7 @@ def get_search_files(self): @property def lib_ldf_mode(self): - mode = LibBuilderBase.lib_ldf_mode.fget(self) # pylint: disable=no-member + mode = LibBuilderBase.lib_ldf_mode.fget(self) # type: ignore if not mode.startswith("chain"): return mode # parse all project files @@ -957,13 +958,13 @@ def lib_ldf_mode(self): @property def src_filter(self): - # pylint: disable=no-member - return self.env.get("SRC_FILTER") or LibBuilderBase.src_filter.fget(self) + # type: ignore + return self.env.get("SRC_FILTER") or LibBuilderBase.src_filter.fget(self) # type: ignore @property def build_flags(self): - # pylint: disable=no-member - return self.env.get("SRC_BUILD_FLAGS") or LibBuilderBase.build_flags.fget(self) + # type: ignore + return self.env.get("SRC_BUILD_FLAGS") or LibBuilderBase.build_flags.fget(self) # type: ignore @property def dependencies(self): @@ -1067,7 +1068,9 @@ def GetLibSourceDirs(env): ] -def IsCompatibleLibBuilder(env, lb, verbose=int(ARGUMENTS.get("PIOVERBOSE", 0))): +def IsCompatibleLibBuilder(env, lb, verbose=None): + if verbose is None: + verbose = int(ARGUMENTS.get("PIOVERBOSE", 0)) compat_mode = lb.lib_compat_mode if lb.name in env.GetProjectOption("lib_ignore", []): if verbose: @@ -1180,8 +1183,8 @@ def _print_deps_tree(root, level=0): click.echo( " (License: %s, " % (_get_lib_license(pkg) or "Unknown"), nl=False ) - if pkg.metadata and pkg.metadata.spec.external: - click.echo("URI: %s, " % pkg.metadata.spec.uri, nl=False) + if pkg.metadata and pkg.metadata.spec.external: # type: ignore + click.echo("URI: %s, " % pkg.metadata.spec.uri, nl=False) # type: ignore click.echo("Path: %s" % lb.path, nl=False) click.echo(")", nl=False) click.echo("") @@ -1193,7 +1196,7 @@ def _print_deps_tree(root, level=0): if "test" in env["BUILD_TYPE"]: project.env.ConfigureTestTarget() - ldf_mode = LibBuilderBase.lib_ldf_mode.fget(project) # pylint: disable=no-member + ldf_mode = LibBuilderBase.lib_ldf_mode.fget(project) # type: ignore click.echo("LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf") click.echo( diff --git a/platformio/builder/tools/piomaxlen.py b/platformio/builder/tools/piomaxlen.py index 8d45317cc2..414afeaa8f 100644 --- a/platformio/builder/tools/piomaxlen.py +++ b/platformio/builder/tools/piomaxlen.py @@ -16,9 +16,9 @@ import os import re -from SCons.Platform import TempFileMunge # pylint: disable=import-error -from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error -from SCons.Subst import quote_spaces # pylint: disable=import-error +from SCons.Platform import TempFileMunge # type: ignore +from SCons.Script import COMMAND_LINE_TARGETS # type: ignore +from SCons.Subst import quote_spaces # type: ignore from platformio.compat import IS_WINDOWS, hashlib_encode_data @@ -76,14 +76,14 @@ def exists(env): def generate(env): if not exists(env): return env - kwargs = dict( - _long_sources_hook=long_sources_hook, - TEMPFILE=TempFileMunge, - MAXLINELENGTH=MAX_LINE_LENGTH, - TEMPFILEARGESCFUNC=tempfile_arg_esc_func, - TEMPFILESUFFIX=".tmp", - TEMPFILEDIR="$BUILD_DIR", - ) + kwargs = { + "_long_sources_hook": long_sources_hook, + "TEMPFILE": TempFileMunge, + "MAXLINELENGTH": MAX_LINE_LENGTH, + "TEMPFILEARGESCFUNC": tempfile_arg_esc_func, + "TEMPFILESUFFIX": ".tmp", + "TEMPFILEDIR": "$BUILD_DIR", + } for name in ("LINKCOM", "ASCOM", "ASPPCOM", "CCCOM", "CXXCOM"): kwargs[name] = "${TEMPFILE('%s','$%sSTR')}" % (env.get(name), name) diff --git a/platformio/builder/tools/piomisc.py b/platformio/builder/tools/piomisc.py index 9652c400d1..5de331e2bb 100644 --- a/platformio/builder/tools/piomisc.py +++ b/platformio/builder/tools/piomisc.py @@ -35,7 +35,7 @@ def GetCompilerType(env): # pylint: disable=too-many-return-statements return None if result["returncode"] != 0: return None - output = "".join([result["out"], result["err"]]).lower() + output = "".join([result["out"], result["err"]]).lower() # type: ignore if "clang version" in output: return "clang" if "gcc" in output: diff --git a/platformio/builder/tools/pioplatform.py b/platformio/builder/tools/pioplatform.py index f99a6ec5a8..d7708b716d 100644 --- a/platformio/builder/tools/pioplatform.py +++ b/platformio/builder/tools/pioplatform.py @@ -15,9 +15,9 @@ import os import sys -from SCons.Script import ARGUMENTS # pylint: disable=import-error -from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error -from SCons.Script import DefaultEnvironment # pylint: disable=import-error +from SCons.Script import ARGUMENTS # type: ignore +from SCons.Script import COMMAND_LINE_TARGETS # type: ignore +from SCons.Script import DefaultEnvironment # type: ignore from platformio import fs, util from platformio.compat import IS_MACOS, IS_WINDOWS @@ -158,9 +158,9 @@ def _get_plaform_data(): if ( int(ARGUMENTS.get("PIOVERBOSE", 0)) and pkg_metadata - and pkg_metadata.spec.external + and pkg_metadata.spec.external # type: ignore ): - data.append("(%s)" % pkg_metadata.spec.uri) + data.append("(%s)" % pkg_metadata.spec.uri) # type: ignore if board_config: data.extend([">", board_config.get("name")]) return data @@ -194,7 +194,7 @@ def _get_debug_data(): "DEBUG:", "Current", "(%s)" - % board_config.get_debug_tool_name(env.GetProjectOption("debug_tool")), + % board_config.get_debug_tool_name(env.GetProjectOption("debug_tool")), # type: ignore ] onboard = [] external = [] diff --git a/platformio/builder/tools/piosize.py b/platformio/builder/tools/piosize.py index 3ac24311e8..cd6ca488d9 100644 --- a/platformio/builder/tools/piosize.py +++ b/platformio/builder/tools/piosize.py @@ -50,10 +50,10 @@ def _get_symbol_locations(env, elf_path, addrs): return {} cmd = [env.subst("$CC").replace("-gcc", "-addr2line"), "-e", elf_path] result = _run_tool(cmd, env, addrs) - locations = [line for line in result["out"].split("\n") if line] + locations = [line for line in result["out"].split("\n") if line] # type: ignore assert len(addrs) == len(locations) - return dict(zip(addrs, [loc.strip() for loc in locations])) + return dict(zip(addrs, [loc.strip() for loc in locations], strict=False)) # type: ignore def _get_demangled_names(env, mangled_names): @@ -62,13 +62,13 @@ def _get_demangled_names(env, mangled_names): result = _run_tool( [env.subst("$CC").replace("-gcc", "-c++filt")], env, mangled_names ) - demangled_names = [line for line in result["out"].split("\n") if line] + demangled_names = [line for line in result["out"].split("\n") if line] # type: ignore assert len(mangled_names) == len(demangled_names) return dict( zip( mangled_names, - [dn.strip().replace("::__FUNCTION__", "") for dn in demangled_names], + [dn.strip().replace("::__FUNCTION__", "") for dn in demangled_names], strict=False, # type: ignore ) ) diff --git a/platformio/builder/tools/piotarget.py b/platformio/builder/tools/piotarget.py index 287528eb05..7e3b2c14bf 100644 --- a/platformio/builder/tools/piotarget.py +++ b/platformio/builder/tools/piotarget.py @@ -14,9 +14,9 @@ import os -from SCons.Action import Action # pylint: disable=import-error -from SCons.Script import ARGUMENTS # pylint: disable=import-error -from SCons.Script import AlwaysBuild # pylint: disable=import-error +from SCons.Action import Action # type: ignore +from SCons.Script import ARGUMENTS # type: ignore +from SCons.Script import AlwaysBuild # type: ignore from platformio import compat, fs @@ -74,9 +74,9 @@ def AddTarget( # pylint: disable=too-many-arguments,too-many-positional-argumen if "__PIO_TARGETS" not in env: env["__PIO_TARGETS"] = {} assert name not in env["__PIO_TARGETS"] - env["__PIO_TARGETS"][name] = dict( - name=name, title=title, description=description, group=group - ) + env["__PIO_TARGETS"][name] = { + "name": name, "title": title, "description": description, "group": group + } target = env.Alias(name, dependencies, actions) if always_build: AlwaysBuild(target) @@ -84,11 +84,11 @@ def AddTarget( # pylint: disable=too-many-arguments,too-many-positional-argumen def AddPlatformTarget(env, *args, **kwargs): - return env.AddTarget(group="Platform", *args, **kwargs) + return env.AddTarget(*args, group="Platform", **kwargs) def AddCustomTarget(env, *args, **kwargs): - return env.AddTarget(group="Custom", *args, **kwargs) + return env.AddTarget(*args, group="Custom", **kwargs) def DumpTargets(env): @@ -97,7 +97,7 @@ def DumpTargets(env): if env.PioPlatform().is_embedded() and not any( t["group"] == "Platform" for t in targets.values() ): - targets["upload"] = dict(name="upload", group="Platform", title="Upload") + targets["upload"] = {"name": "upload", "group": "Platform", "title": "Upload"} return list(targets.values()) diff --git a/platformio/builder/tools/pioupload.py b/platformio/builder/tools/pioupload.py index 224d0b90f8..d34a1a4c09 100644 --- a/platformio/builder/tools/pioupload.py +++ b/platformio/builder/tools/pioupload.py @@ -20,7 +20,7 @@ from shutil import copyfile from time import sleep -from SCons.Script import ARGUMENTS # pylint: disable=import-error +from SCons.Script import ARGUMENTS # type: ignore from serial import Serial, SerialException from platformio import exception, fs @@ -31,12 +31,12 @@ def FlushSerialBuffer(env, port): s = Serial(env.subst(port)) - s.flushInput() - s.setDTR(False) - s.setRTS(False) + s.flushInput() # type: ignore + s.setDTR(False) # type: ignore + s.setRTS(False) # type: ignore sleep(0.1) - s.setDTR(True) - s.setRTS(True) + s.setDTR(True) # type: ignore + s.setRTS(True) # type: ignore s.close() @@ -45,9 +45,9 @@ def TouchSerialPort(env, port, baudrate): print("Forcing reset using %dbps open/close on port %s" % (baudrate, port)) try: s = Serial(port=port, baudrate=baudrate) - s.setDTR(False) + s.setDTR(False) # type: ignore s.close() - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except pass sleep(0.4) # DO NOT REMOVE THAT (required by SAM-BA based boards) @@ -59,7 +59,7 @@ def WaitForNewSerialPort(env, before): elapsed = 0 before = [p["port"] for p in before] while elapsed < 5 and new_port is None: - now = [p["port"] for p in list_serial_ports()] + now = [p["port"] for p in list_serial_ports()] # type: ignore for p in now: if p not in before: new_port = p @@ -114,7 +114,7 @@ def AutodetectUploadPort(*args, **kwargs): board_config=env.BoardConfig() if "BOARD" in env else None, upload_protocol=upload_protocol, prefer_gdb_port="blackmagic" in upload_protocol, - verbose=int(ARGUMENTS.get("PIOVERBOSE", 0)), + verbose=int(ARGUMENTS.get("PIOVERBOSE", 0)), # type: ignore ).find(initial_port) ) @@ -177,14 +177,14 @@ def _get_size_output(): result = exec_command(env.subst(cmd), env=sysenv) if result["returncode"] != 0: return None - return result["out"].strip() + return result["out"].strip() # type: ignore def _calculate_size(output, pattern): if not output or not pattern: return -1 size = 0 regexp = re.compile(pattern) - for line in output.split("\n"): + for line in output.split("\n"): # type: ignore line = line.strip() if not line: continue diff --git a/platformio/cache.py b/platformio/cache.py index 20901545e4..c7191e888f 100644 --- a/platformio/cache.py +++ b/platformio/cache.py @@ -144,7 +144,7 @@ def _lock_dbindex(self): self._lockfile = LockFile(self.cache_dir) try: self._lockfile.acquire() - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except return False return True diff --git a/platformio/check/cli.py b/platformio/check/cli.py index ca591f0315..031c3cba4c 100644 --- a/platformio/check/cli.py +++ b/platformio/check/cli.py @@ -48,7 +48,7 @@ @click.option("-f", "--src-filters", multiple=True) @click.option("--flags", multiple=True) @click.option( - "--severity", multiple=True, type=click.Choice(DefectItem.SEVERITY_LABELS.values()) + "--severity", multiple=True, type=click.Choice(DefectItem.SEVERITY_LABELS.values()) # type: ignore ) @click.option("-s", "--silent", is_flag=True) @click.option("-v", "--verbose", is_flag=True) @@ -56,7 +56,7 @@ @click.option( "--fail-on-defect", multiple=True, - type=click.Choice(DefectItem.SEVERITY_LABELS.values()), + type=click.Choice(DefectItem.SEVERITY_LABELS.values()), # type: ignore ) @click.option("--skip-packages", is_flag=True) def cli( # pylint: disable=too-many-positional-arguments @@ -127,19 +127,19 @@ def cli( # pylint: disable=too-many-positional-arguments ) ) - tool_options = dict( - verbose=verbose, - silent=silent, - src_filters=env_src_filters, - flags=flags or env_options.get("check_flags"), - severity=( + tool_options = { + "verbose": verbose, + "silent": silent, + "src_filters": env_src_filters, + "flags": flags or env_options.get("check_flags"), + "severity": ( [DefectItem.SEVERITY_LABELS[DefectItem.SEVERITY_HIGH]] if silent else severity or config.get("env:" + envname, "check_severity") ), - skip_packages=skip_packages or env_options.get("check_skip_packages"), - platform_packages=env_options.get("platform_packages"), - ) + "skip_packages": skip_packages or env_options.get("check_skip_packages"), + "platform_packages": env_options.get("platform_packages"), + } for tool in config.get("env:" + envname, "check_tool"): if skipenv: @@ -266,7 +266,7 @@ def print_defects_stats(results): component_stats = {} for r in results: - for k, v in r.get("stats", {}).items(): + for k, _v in r.get("stats", {}).items(): if not component_stats.get(k): component_stats[k] = Counter() component_stats[k].update(r["stats"][k]) @@ -281,7 +281,7 @@ def print_defects_stats(results): tool_defect = [v.get(s, 0) for s in severity_labels] tabular_data.append([k] + tool_defect) - total = ["Total"] + [sum(d) for d in list(zip(*tabular_data))[1:]] + total = ["Total"] + [sum(d) for d in list(zip(*tabular_data, strict=False))[1:]] # type: ignore tabular_data.sort() tabular_data.append([]) # Empty line as delimiter tabular_data.append(total) @@ -333,7 +333,7 @@ def print_check_summary(results, verbose=False): for s in ("Environment", "Tool", "Status", "Duration") ], ), - err=failed_nums, + err=failed_nums, # type: ignore ) util.print_labeled_bar( @@ -343,6 +343,6 @@ def print_check_summary(results, verbose=False): succeeded_nums, util.humanize_duration_time(duration), ), - is_error=failed_nums, + is_error=failed_nums, # type: ignore fg="red" if failed_nums else "green", ) diff --git a/platformio/check/defect.py b/platformio/check/defect.py index 9dc8ef03d9..3d3eda74d9 100644 --- a/platformio/check/defect.py +++ b/platformio/check/defect.py @@ -51,8 +51,8 @@ def __init__( # pylint: disable=too-many-positional-arguments self.cwe = cwe self.id = id self.file = file or "unknown" - if file.lower().startswith(get_project_dir().lower()): - self.file = os.path.relpath(file, get_project_dir()) + if file.lower().startswith(get_project_dir().lower()): # type: ignore + self.file = os.path.relpath(file, get_project_dir()) # type: ignore def __repr__(self): defect_color = None diff --git a/platformio/check/tools/base.py b/platformio/check/tools/base.py index ccf331f453..8a02f418c1 100644 --- a/platformio/check/tools/base.py +++ b/platformio/check/tools/base.py @@ -106,8 +106,8 @@ def _extract_defines(language, includes_file): click.echo(result["out"]) click.echo(result["err"]) - for line in result["out"].split("\n"): - tokens = line.strip().split(" ", 2) + for line in result["out"].split("\n"): # type: ignore + tokens = line.strip().split(" ", 2) # type: ignore if not tokens or tokens[0] != "#define": continue if len(tokens) > 2: diff --git a/platformio/check/tools/clangtidy.py b/platformio/check/tools/clangtidy.py index 496acc7c89..ca89f86283 100644 --- a/platformio/check/tools/clangtidy.py +++ b/platformio/check/tools/clangtidy.py @@ -46,7 +46,7 @@ def parse_defect(self, raw_line): # pylint: disable=arguments-differ elif category == "warning": severity = DefectItem.SEVERITY_MEDIUM - return DefectItem(severity, category, message, file_, line, column, defect_id) + return DefectItem(severity, category, message, file_, line, column, defect_id) # type: ignore @staticmethod def is_check_successful(cmd_result): @@ -55,7 +55,7 @@ def is_check_successful(cmd_result): return cmd_result["returncode"] < 2 def configure_command(self): - tool_path = join(self.get_tool_dir("tool-clangtidy"), "clang-tidy") + tool_path = join(self.get_tool_dir("tool-clangtidy"), "clang-tidy") # type: ignore cmd = [tool_path, "--quiet"] flags = self.get_flags("clangtidy") @@ -74,7 +74,7 @@ def configure_command(self): cmd.extend(flags + src_files + ["--"]) cmd.extend( - ["-D%s" % d for d in self.cpp_defines + self.toolchain_defines["c++"]] + ["-D%s" % d for d in self.cpp_defines + self.toolchain_defines["c++"]] # type: ignore ) includes = [] diff --git a/platformio/check/tools/cppcheck.py b/platformio/check/tools/cppcheck.py index c3c595373c..8cd781d297 100644 --- a/platformio/check/tools/cppcheck.py +++ b/platformio/check/tools/cppcheck.py @@ -103,7 +103,7 @@ def parse_defect(self, raw_line): # pylint: disable=arguments-differ return DefectItem(**args) def configure_command(self, language, src_file): # pylint: disable=arguments-differ - tool_path = os.path.join(self.get_tool_dir("tool-cppcheck"), "cppcheck") + tool_path = os.path.join(self.get_tool_dir("tool-cppcheck"), "cppcheck") # type: ignore cmd = [ tool_path, @@ -148,14 +148,14 @@ def configure_command(self, language, src_file): # pylint: disable=arguments-di cmd.append("-" + self.convert_language_standard(flag)) cmd.extend( - ["-D%s" % d for d in self.cpp_defines + self.toolchain_defines[language]] + ["-D%s" % d for d in self.cpp_defines + self.toolchain_defines[language]] # type: ignore ) cmd.extend(flags) cmd.extend( "--include=" + inc - for inc in self.get_forced_includes(build_flags, self.cpp_includes) + for inc in self.get_forced_includes(build_flags, self.cpp_includes) # type: ignore ) cmd.append("--includes-file=%s" % self._generate_inc_file()) cmd.append('"%s"' % src_file) diff --git a/platformio/check/tools/pvsstudio.py b/platformio/check/tools/pvsstudio.py index 20979a0019..9bb8e1655d 100644 --- a/platformio/check/tools/pvsstudio.py +++ b/platformio/check/tools/pvsstudio.py @@ -33,8 +33,8 @@ def __init__(self, *args, **kwargs): self._tmp_output_file = self._generate_tmp_file_path() + ".pvs" self._tmp_cfg_file = self._generate_tmp_file_path() + ".cfg" self._tmp_cmd_file = self._generate_tmp_file_path() + ".cmd" - self.tool_path = os.path.join( - self.get_tool_dir("tool-pvs-studio"), + self.tool_path = os.path.join( # type: ignore + self.get_tool_dir("tool-pvs-studio"), # type: ignore "x64" if IS_WINDOWS else "bin", "pvs-studio", ) @@ -74,8 +74,8 @@ def _process_defects(self, defects): self._on_defect_callback(defect) def _demangle_report(self, output_file): - converter_tool = os.path.join( - self.get_tool_dir("tool-pvs-studio"), + converter_tool = os.path.join( # type: ignore + self.get_tool_dir("tool-pvs-studio"), # type: ignore "HtmlGenerator" if IS_WINDOWS else os.path.join("bin", "plog-converter"), ) @@ -111,24 +111,24 @@ def parse_defects(self, output_file): try: defects_data = fromstring(report) - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except click.echo("Error: Couldn't decode generated report!") self._bad_input = True return [] for table in defects_data.iter("PVS-Studio_Analysis_Log"): - message = table.find("Message").text - category = table.find("ErrorType").text - line = table.find("Line").text - file_ = table.find("File").text - defect_id = table.find("ErrorCode").text - cwe = table.find("CWECode") + message = table.find("Message").text # type: ignore + category = table.find("ErrorType").text # type: ignore + line = table.find("Line").text # type: ignore + file_ = table.find("File").text # type: ignore + defect_id = table.find("ErrorCode").text # type: ignore + cwe = table.find("CWECode") # type: ignore cwe_id = None if cwe is not None: - cwe_id = cwe.text.lower().replace("cwe-", "") - misra = table.find("MISRA") + cwe_id = cwe.text.lower().replace("cwe-", "") # type: ignore + misra = table.find("MISRA") # type: ignore if misra is not None: - message += " [%s]" % misra.text + message += " [%s]" % misra.text # type: ignore severity = DefectItem.SEVERITY_LOW if category == "error": @@ -138,7 +138,7 @@ def parse_defects(self, output_file): defects.append( DefectItem( - severity, category, message, file_, line, id=defect_id, cwe=cwe_id + severity, category, message, file_, line, id=defect_id, cwe=cwe_id # type: ignore ) ) @@ -179,7 +179,7 @@ def configure_command(self, src_file): # pylint: disable=arguments-differ def _generate_tmp_file_path(self): # pylint: disable=protected-access - return os.path.join(self._tmp_dir, next(tempfile._get_candidate_names())) + return os.path.join(self._tmp_dir, next(tempfile._get_candidate_names())) # type: ignore def _prepare_preprocessed_file(self, src_file): if os.path.isfile(self._tmp_preprocessed_file): diff --git a/platformio/cli.py b/platformio/cli.py index a2a707ad70..a83b1452f6 100644 --- a/platformio/cli.py +++ b/platformio/cli.py @@ -24,7 +24,7 @@ class PlatformioCLI(click.MultiCommand): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._pio_root_path = Path(__file__).parent - self._pio_cmd_aliases = dict(package="pkg") + self._pio_cmd_aliases = {"package": "pkg"} def _find_pio_commands(self): def _to_module_path(p): @@ -85,14 +85,14 @@ def invoke(self, ctx): return super().invoke(ctx) def list_commands(self, ctx): - return sorted(list(self._find_pio_commands())) + return sorted(self._find_pio_commands()) def get_command(self, ctx, cmd_name): commands = self._find_pio_commands() if cmd_name not in commands: return self._handle_obsolate_command(ctx, cmd_name) module = importlib.import_module(commands[cmd_name]) - return getattr(module, "cli") + return module.cli @staticmethod def _handle_obsolate_command(ctx, cmd_name): diff --git a/platformio/commands/ci.py b/platformio/commands/ci.py index 5a36c00988..9cd9ba1995 100644 --- a/platformio/commands/ci.py +++ b/platformio/commands/ci.py @@ -77,7 +77,7 @@ def cli( # pylint: disable=too-many-arguments,too-many-positional-arguments, to verbose, ): if not src and os.getenv("PLATFORMIO_CI_SRC"): - src = validate_path(ctx, None, os.getenv("PLATFORMIO_CI_SRC").split(":")) + src = validate_path(ctx, None, os.getenv("PLATFORMIO_CI_SRC").split(":")) # type: ignore if not src: raise click.BadParameter("Missing argument 'src'") @@ -87,7 +87,7 @@ def cli( # pylint: disable=too-many-arguments,too-many-positional-arguments, to if not os.path.isdir(build_dir): os.makedirs(build_dir) - for dir_name, patterns in dict(lib=lib, src=src).items(): + for dir_name, patterns in {"lib": lib, "src": src}.items(): if not patterns: continue contents = [] diff --git a/platformio/commands/device/__init__.py b/platformio/commands/device/__init__.py index d78b00355a..74911950ec 100644 --- a/platformio/commands/device/__init__.py +++ b/platformio/commands/device/__init__.py @@ -14,5 +14,8 @@ # pylint: disable=unused-import from platformio.device.monitor.filters.base import ( - DeviceMonitorFilterBase as DeviceMonitorFilter, + DeviceMonitorFilterBase as DeviceMonitorFilterBase, ) + +# Re-export +DeviceMonitorFilter = DeviceMonitorFilterBase diff --git a/platformio/commands/lib.py b/platformio/commands/lib.py index 989797dcb1..d4f3e23a53 100644 --- a/platformio/commands/lib.py +++ b/platformio/commands/lib.py @@ -241,7 +241,7 @@ def lib_update( # pylint: disable=too-many-arguments,too-many-positional-argume _libraries = libraries or lib_deps or lm.get_installed() result = [] - for library in _libraries: + for library in _libraries: # type: ignore spec = None pkg = None if isinstance(library, PackageItem): @@ -339,7 +339,7 @@ def lib_search( # pylint: disable=unused-argument result = regclient.fetch_json_data( "get", "/v2/lib/search", - params=dict(query=" ".join(query), page=page), + params={"query": " ".join(query), "page": page}, x_cache_valid="1d", ) return click.echo(json.dumps(result)) diff --git a/platformio/commands/platform.py b/platformio/commands/platform.py index ccde956bb8..26c97dd88c 100644 --- a/platformio/commands/platform.py +++ b/platformio/commands/platform.py @@ -116,7 +116,7 @@ def platform_list(ctx, json_output): platforms = [] pm = PlatformPackageManager() - for pkg in pm.get_installed(): + for pkg in pm.get_installed(): # type: ignore platforms.append( _get_installed_platform_data(pkg, with_boards=False, expose_packages=False) ) @@ -253,7 +253,7 @@ def platform_update( # pylint: disable=too-many-locals,too-many-arguments,too-m pm.set_log_level(logging.WARN if silent else logging.DEBUG) platforms = platforms or pm.get_installed() result = [] - for platform in platforms: + for platform in platforms: # type: ignore spec = None pkg = None if isinstance(platform, PackageItem): @@ -298,19 +298,19 @@ def _get_platform_data(*args, **kwargs): def _get_installed_platform_data(platform, with_boards=True, expose_packages=True): p = PlatformFactory.new(platform) - data = dict( - name=p.name, - title=p.title, - description=p.description, - version=p.version, - homepage=p.homepage, - url=p.homepage, - repository=p.repository_url, - license=p.license, - forDesktop=not p.is_embedded(), - frameworks=sorted(list(p.frameworks) if p.frameworks else []), - packages=list(p.packages) if p.packages else [], - ) + data = { + "name": p.name, + "title": p.title, + "description": p.description, + "version": p.version, + "homepage": p.homepage, + "url": p.homepage, + "repository": p.repository_url, + "license": p.license, + "forDesktop": not p.is_embedded(), + "frameworks": sorted(list(p.frameworks) if p.frameworks else []), + "packages": list(p.packages) if p.packages else [], + } # if dump to API # del data['version'] @@ -336,12 +336,12 @@ def _get_installed_platform_data(platform, with_boards=True, expose_packages=Tru pkg.metadata.name: p.pm.load_manifest(pkg) for pkg in p.get_installed_packages() } for name, options in p.packages.items(): - item = dict( - name=name, - type=p.get_package_type(name), - requirements=options.get("version"), - optional=options.get("optional") is True, - ) + item = { + "name": name, + "type": p.get_package_type(name), + "requirements": options.get("version"), + "optional": options.get("optional") is True, + } if name in installed_pkgs: for key, value in installed_pkgs[name].items(): if key not in ("url", "version", "description"): @@ -366,20 +366,20 @@ def _get_registry_platform_data( # pylint: disable=unused-argument if not _data: return None - data = dict( - ownername=_data.get("ownername"), - name=_data["name"], - title=_data["title"], - description=_data["description"], - homepage=_data["homepage"], - repository=_data["repository"], - url=_data["url"], - license=_data["license"], - forDesktop=_data["forDesktop"], - frameworks=_data["frameworks"], - packages=_data["packages"], - versions=_data.get("versions"), - ) + data = { + "ownername": _data.get("ownername"), + "name": _data["name"], + "title": _data["title"], + "description": _data["description"], + "homepage": _data["homepage"], + "repository": _data["repository"], + "url": _data["url"], + "license": _data["license"], + "forDesktop": _data["forDesktop"], + "frameworks": _data["frameworks"], + "packages": _data["packages"], + "versions": _data.get("versions"), + } if with_boards: data["boards"] = [ diff --git a/platformio/commands/upgrade.py b/platformio/commands/upgrade.py index d8ba386e6b..1a12a19b41 100644 --- a/platformio/commands/upgrade.py +++ b/platformio/commands/upgrade.py @@ -124,7 +124,7 @@ def get_latest_version(): if not str(VERSION[2]).isdigit(): try: return get_develop_latest_version() - except: # pylint: disable=bare-except + except Exception: # pylint: disable=broad-except pass return get_pypi_latest_version() except Exception as exc: diff --git a/platformio/compat.py b/platformio/compat.py index d545509991..fc5b74584b 100644 --- a/platformio/compat.py +++ b/platformio/compat.py @@ -20,34 +20,13 @@ import os import shlex import sys +from asyncio import create_task as aio_create_task +from asyncio import get_running_loop as aio_get_running_loop +from asyncio import to_thread as aio_to_thread +from shlex import join as shlex_join from platformio.exception import UserSideException -if sys.version_info >= (3, 7): - from asyncio import create_task as aio_create_task - from asyncio import get_running_loop as aio_get_running_loop -else: - from asyncio import ensure_future as aio_create_task - from asyncio import get_event_loop as aio_get_running_loop - - -if sys.version_info >= (3, 8): - from shlex import join as shlex_join -else: - - def shlex_join(split_command): - return " ".join(shlex.quote(arg) for arg in split_command) - - -if sys.version_info >= (3, 9): - from asyncio import to_thread as aio_to_thread -else: - try: - from starlette.concurrency import run_in_threadpool as aio_to_thread - except ImportError: - pass - - PY2 = sys.version_info[0] == 2 # DO NOT REMOVE IT. ESP8266/ESP32 depend on it PY36 = sys.version_info[0:2] == (3, 6) IS_CYGWIN = sys.platform.startswith("cygwin") @@ -62,12 +41,7 @@ def is_bytes(x): def isascii(text): - if sys.version_info >= (3, 7): - return text.isascii() - for c in text or "": - if ord(c) > 127: - return False - return True + return text.isascii() def is_terminal(): @@ -95,7 +69,9 @@ def hashlib_encode_data(data): def load_python_module(name, pathname): spec = importlib.util.spec_from_file_location(name, pathname) + assert spec is not None module = importlib.util.module_from_spec(spec) + assert spec.loader is not None spec.loader.exec_module(module) return module @@ -146,3 +122,20 @@ def is_proxy_set(socks=False): continue return True return False + + +__all__ = [ + "aio_create_task", + "aio_get_running_loop", + "aio_to_thread", + "shlex_join", + "is_bytes", + "isascii", + "is_terminal", + "ci_strings_are_equal", + "hashlib_encode_data", + "load_python_module", + "get_filesystem_encoding", + "get_locale_encoding", + "get_object_members", +] diff --git a/platformio/debug/cli.py b/platformio/debug/cli.py index d29b44d066..f2c9a4eba8 100644 --- a/platformio/debug/cli.py +++ b/platformio/debug/cli.py @@ -37,7 +37,7 @@ @click.command( "debug", - context_settings=dict(ignore_unknown_options=True), + context_settings={"ignore_unknown_options": True}, short_help="Unified Debugger", ) @click.option( diff --git a/platformio/debug/config/base.py b/platformio/debug/config/base.py index 1caae23f73..de61024487 100644 --- a/platformio/debug/config/base.py +++ b/platformio/debug/config/base.py @@ -144,7 +144,7 @@ def speed(self): @property def server_ready_pattern(self): return self.env_options.get( - "debug_server_ready_pattern", (self.server or {}).get("ready_pattern") + "debug_server_ready_pattern", (self.server or {}).get("ready_pattern") # type: ignore ) def _load_build_data(self): @@ -192,10 +192,10 @@ def _configure_server(self): self.platform.install_package(server_package) server_package_dir = self.platform.get_package_dir(server_package) result.update( - dict( - cwd=server_package_dir if server_package else None, - executable=result.get("executable"), - arguments=[ + { + "cwd": server_package_dir if server_package else None, + "executable": result.get("executable"), + "arguments": [ ( a.replace("$PACKAGE_DIR", server_package_dir) if server_package_dir @@ -203,7 +203,7 @@ def _configure_server(self): ) for a in result.get("arguments", []) ], - ) + } ) return self.reveal_patterns(result) if result else None @@ -245,10 +245,10 @@ def _replace(text): if isinstance(value, string_types): source[key] = _replace(value) elif isinstance(value, (list, dict)) and recursive: - source[key] = self.reveal_patterns(value, patterns) + source[key] = self.reveal_patterns(value, patterns) # type: ignore data = json.dumps(source) if any(("$" + key) in data for key in patterns): - source = self.reveal_patterns(source, patterns) + source = self.reveal_patterns(source, patterns) # type: ignore return source diff --git a/platformio/debug/config/blackmagic.py b/platformio/debug/config/blackmagic.py index 370fdb7ebd..b34baeb1e4 100644 --- a/platformio/debug/config/blackmagic.py +++ b/platformio/debug/config/blackmagic.py @@ -52,7 +52,7 @@ class BlackmagicDebugConfig(DebugConfigBase): @property def port(self): # pylint: disable=assignment-from-no-return - initial_port = DebugConfigBase.port.fget(self) + initial_port = DebugConfigBase.port.fget(self) # type: ignore if initial_port and not is_pattern_port(initial_port): return initial_port port = SerialPortFinder( diff --git a/platformio/debug/helpers.py b/platformio/debug/helpers.py index fa03725d41..bef5f13722 100644 --- a/platformio/debug/helpers.py +++ b/platformio/debug/helpers.py @@ -34,7 +34,7 @@ class GDBMIConsoleStream(BytesIO): # pylint: disable=too-few-public-methods STDOUT = sys.stdout def write(self, text): - self.STDOUT.write(escape_gdbmi_stream("~", text)) + self.STDOUT.write(escape_gdbmi_stream("~", text)) # type: ignore self.STDOUT.flush() diff --git a/platformio/debug/process/base.py b/platformio/debug/process/base.py index 6ba8c70ec3..550062962a 100644 --- a/platformio/debug/process/base.py +++ b/platformio/debug/process/base.py @@ -18,10 +18,10 @@ import sys import time +from platformio.compat import aio_create_task # type: ignore +from platformio.compat import aio_get_running_loop # type: ignore from platformio.compat import ( IS_WINDOWS, - aio_create_task, - aio_get_running_loop, get_locale_encoding, ) @@ -150,5 +150,5 @@ def terminate(self): try: self.transport.kill() self.transport.close() - except: # pylint: disable=bare-except + except Exception: # pylint: disable=broad-except pass diff --git a/platformio/debug/process/client.py b/platformio/debug/process/client.py index d508bdaea1..d87aa5eda2 100644 --- a/platformio/debug/process/client.py +++ b/platformio/debug/process/client.py @@ -88,7 +88,7 @@ def _kill_previous_session(self): kill = ["kill", pid] try: proc.exec_command(kill) - except: # pylint: disable=bare-except + except Exception: # pylint: disable=broad-except pass def _lock_session(self, pid): diff --git a/platformio/debug/process/gdb.py b/platformio/debug/process/gdb.py index 29a8ba3a23..a759861010 100644 --- a/platformio/debug/process/gdb.py +++ b/platformio/debug/process/gdb.py @@ -17,7 +17,7 @@ import time from platformio import telemetry -from platformio.compat import aio_get_running_loop, is_bytes +from platformio.compat import aio_get_running_loop, is_bytes # type: ignore from platformio.debug import helpers from platformio.debug.exception import DebugInitError from platformio.debug.process.client import DebugClientProcess @@ -122,8 +122,8 @@ def stdin_data_received(self, data): if b"-gdb-exit" in data or data.strip() in (b"q", b"quit"): # Allow terminating via SIGINT/CTRL+C signal.signal(signal.SIGINT, signal.default_int_handler) - self.transport.get_pipe_transport(0).write(b"pio_reset_run_target\n") - self.transport.get_pipe_transport(0).write(data) + self.transport.get_pipe_transport(0).write(b"pio_reset_run_target\n") # type: ignore + self.transport.get_pipe_transport(0).write(data) # type: ignore def stdout_data_received(self, data): super().stdout_data_received(data) @@ -136,7 +136,7 @@ def stdout_data_received(self, data): def console_log(self, msg): if helpers.is_gdbmi_mode(): msg = helpers.escape_gdbmi_stream("~", msg) - self.stdout_data_received(msg if is_bytes(msg) else msg.encode()) + self.stdout_data_received(msg if is_bytes(msg) else msg.encode()) # type: ignore def _auto_exec_continue(self): auto_exec_delay = 0.5 # in seconds @@ -155,11 +155,11 @@ def _auto_exec_continue(self): "PlatformIO: More configuration options -> https://bit.ly/pio-debug\n" ) if self.debug_config.platform.is_embedded(): - self.transport.get_pipe_transport(0).write( + self.transport.get_pipe_transport(0).write( # type: ignore b"0-exec-continue\n" if helpers.is_gdbmi_mode() else b"continue\n" ) else: - self.transport.get_pipe_transport(0).write( + self.transport.get_pipe_transport(0).write( # type: ignore b"0-exec-run\n" if helpers.is_gdbmi_mode() else b"run\n" ) self._target_is_running = True @@ -178,4 +178,4 @@ def _handle_error(self, data): telemetry.log_debug_exception( DebugInitError(self._errors_buffer.decode()), self.debug_config ) - self.transport.close() + self.transport.close() # type: ignore diff --git a/platformio/device/finder.py b/platformio/device/finder.py index 7dbfa3d059..616f44660b 100644 --- a/platformio/device/finder.py +++ b/platformio/device/finder.py @@ -57,7 +57,7 @@ def parse_udev_rules_hwids(path): def is_pattern_port(port): if not port: return False - return set(["*", "?", "[", "]"]) & set(port) + return {"*", "?", "[", "]"} & set(port) def find_mbed_disk(initial_port): @@ -74,7 +74,7 @@ def find_mbed_disk(initial_port): mbed_pages = [os.path.join(item["path"], n) for n in ("mbed.htm", "mbed.html")] if any(os.path.isfile(p) for p in mbed_pages): return item["path"] - if item["name"] and any(l in item["name"].lower() for l in msdlabels): + if item["name"] and any(label in item["name"].lower() for label in msdlabels): return item["path"] return None @@ -83,7 +83,7 @@ def is_serial_port_ready(port, timeout=1): try: serial.Serial(port, timeout=timeout).close() return True - except: # pylint: disable=bare-except + except Exception: # pylint: disable=broad-except pass return False @@ -114,8 +114,8 @@ def normalize_board_hwid(value): @staticmethod def match_serial_port(pattern): for item in list_serial_ports(): - if fnmatch(item["port"], pattern): - return item["port"] + if fnmatch(item["port"], pattern): # type: ignore + return item["port"] # type: ignore return None @staticmethod @@ -151,10 +151,10 @@ def find(self, initial_port=None): # pick the best PID:VID USB device port = best_port = None for item in list_serial_ports(): - if self.ensure_ready and not is_serial_port_ready(item["port"]): + if self.ensure_ready and not is_serial_port_ready(item["port"]): # type: ignore continue - port = item["port"] - if "VID:PID" in item["hwid"]: + port = item["port"] # type: ignore + if "VID:PID" in item["hwid"]: # type: ignore best_port = port return best_port or port @@ -184,7 +184,7 @@ def _find_blackmagic_port(self): def _find_board_device(self): hwids = [ self.normalize_board_hwid(hwid) - for hwid in self.board_config.get("build.hwids", []) + for hwid in self.board_config.get("build.hwids", []) # type: ignore ] try: @@ -203,7 +203,7 @@ def wrapper(): click.secho( "TimeoutError: Could not automatically find serial port " "for the `%s` board based on the declared HWIDs=%s" - % (self.board_config.get("name", "unknown"), hwids), + % (self.board_config.get("name", "unknown"), hwids), # type: ignore fg="yellow", err=True, ) @@ -222,7 +222,7 @@ def _find_known_device(self): def _fetch_hwids_from_platforms(): """load from installed dev-platforms""" result = [] - for platform in PlatformPackageManager().get_installed(): + for platform in PlatformPackageManager().get_installed(): # type: ignore p = PlatformFactory.new(platform) for board_config in p.get_boards().values(): for board_hwid in board_config.get("build.hwids", []): diff --git a/platformio/device/list/util.py b/platformio/device/list/util.py index 3847969c43..241723624b 100644 --- a/platformio/device/list/util.py +++ b/platformio/device/list/util.py @@ -18,7 +18,7 @@ import time from glob import glob -from platformio import __version__, exception, proc +from platformio import exception, proc from platformio.compat import IS_MACOS, IS_WINDOWS @@ -57,7 +57,7 @@ def list_logical_devices(): ["wmic", "logicaldisk", "get", "name,VolumeName"] ).get("out", "") devicenamere = re.compile(r"^([A-Z]{1}\:)\s*(\S+)?") - for line in result.split("\n"): + for line in result.split("\n"): # type: ignore match = devicenamere.match(line.strip()) if not match: continue @@ -67,13 +67,16 @@ def list_logical_devices(): pass # try "fsutil" result = proc.exec_command(["fsutil", "fsinfo", "drives"]).get("out", "") - for device in re.findall(r"[A-Z]:\\", result): + assert result is not None + for device in re.findall(r"[A-Z]:\\", result): # type: ignore items.append({"path": device, "name": None}) return items result = proc.exec_command(["df"]).get("out") + assert result is not None + assert isinstance(result, str) devicenamere = re.compile(r"^/.+\d+\%\s+([a-z\d\-_/]+)$", flags=re.I) - for line in result.split("\n"): + for line in result.split("\n"): # type: ignore match = devicenamere.match(line.strip()) if not match: continue @@ -83,14 +86,14 @@ def list_logical_devices(): def list_mdns_services(): try: - import zeroconf # pylint: disable=import-outside-toplevel + import zeroconf # type: ignore except ImportError: result = proc.exec_command( [proc.get_pythonexe_path(), "-m", "pip", "install", "zeroconf"] ) if result.get("returncode") != 0: print(result.get("err")) - import zeroconf # pylint: disable=import-outside-toplevel + import zeroconf # type: ignore class mDNSListener: def __init__(self): diff --git a/platformio/device/monitor/filters/base.py b/platformio/device/monitor/filters/base.py index 5a65f800df..f78034e85f 100644 --- a/platformio/device/monitor/filters/base.py +++ b/platformio/device/monitor/filters/base.py @@ -71,7 +71,7 @@ def register_filters(platform=None, options=None): ) # load package filters pm = ToolPackageManager() - for pkg in pm.get_installed(): + for pkg in pm.get_installed(): # type: ignore load_monitor_filters( os.path.join(pkg.path, "monitor"), prefix="filter_", options=options ) @@ -95,7 +95,7 @@ def load_monitor_filter(path, options=None): name = os.path.basename(path) name = name[: name.find(".")] module = load_python_module("platformio.device.monitor.filters.%s" % name, path) - for cls in get_object_members(module).values(): + for cls in get_object_members(module).values(): # type: ignore if ( not inspect.isclass(cls) or not issubclass(cls, DeviceMonitorFilterBase) @@ -103,5 +103,5 @@ def load_monitor_filter(path, options=None): ): continue obj = cls(options) - miniterm.TRANSFORMATIONS[obj.NAME] = obj + miniterm.TRANSFORMATIONS[obj.NAME] = obj # type: ignore return True diff --git a/platformio/device/monitor/filters/hexlify.py b/platformio/device/monitor/filters/hexlify.py index 40fc203ed0..c3980650a9 100644 --- a/platformio/device/monitor/filters/hexlify.py +++ b/platformio/device/monitor/filters/hexlify.py @@ -18,7 +18,7 @@ class Hexlify(DeviceMonitorFilterBase): - NAME = "hexlify" + NAME = "hexlify" # type: ignore def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -32,7 +32,7 @@ def set_running_terminal(self, terminal): def rx(self, text): result = "" - for c in serial.iterbytes(text): + for c in serial.iterbytes(text): # type: ignore if (self._counter % 16) == 0: result += "\n{:04X} | ".format(self._counter) asciicode = ord(c) diff --git a/platformio/device/monitor/filters/log2file.py b/platformio/device/monitor/filters/log2file.py index 8e00d29708..ad5850291c 100644 --- a/platformio/device/monitor/filters/log2file.py +++ b/platformio/device/monitor/filters/log2file.py @@ -20,7 +20,7 @@ class LogToFile(DeviceMonitorFilterBase): - NAME = "log2file" + NAME = "log2file" # type: ignore def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -42,6 +42,6 @@ def __del__(self): self._log_fp.close() def rx(self, text): - self._log_fp.write(text) - self._log_fp.flush() + self._log_fp.write(text) # type: ignore + self._log_fp.flush() # type: ignore return text diff --git a/platformio/device/monitor/filters/send_on_enter.py b/platformio/device/monitor/filters/send_on_enter.py index c28888cd9a..da214cb37a 100644 --- a/platformio/device/monitor/filters/send_on_enter.py +++ b/platformio/device/monitor/filters/send_on_enter.py @@ -16,7 +16,7 @@ class SendOnEnter(DeviceMonitorFilterBase): - NAME = "send_on_enter" + NAME = "send_on_enter" # type: ignore def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/platformio/device/monitor/filters/time.py b/platformio/device/monitor/filters/time.py index cde4e77261..6478c11f3d 100644 --- a/platformio/device/monitor/filters/time.py +++ b/platformio/device/monitor/filters/time.py @@ -18,7 +18,7 @@ class Timestamp(DeviceMonitorFilterBase): - NAME = "time" + NAME = "time" # type: ignore def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/platformio/device/monitor/terminal.py b/platformio/device/monitor/terminal.py index a3abf857f1..c56aaf7318 100644 --- a/platformio/device/monitor/terminal.py +++ b/platformio/device/monitor/terminal.py @@ -113,7 +113,7 @@ def new_terminal(options): for ts in (term.tx_transformations, term.rx_transformations): for t in ts: try: - t.set_running_terminal(term) + t.set_running_terminal(term) # type: ignore except AttributeError: pass return term diff --git a/platformio/fs.py b/platformio/fs.py index c70a554e75..7c6e0a144e 100644 --- a/platformio/fs.py +++ b/platformio/fs.py @@ -120,7 +120,7 @@ def _rules_to_set(rules_path): result.add(line) return result - if "linux" not in get_systype(): + if "linux" not in get_systype(): # type: ignore return None installed_rules = [ "/etc/udev/rules.d/99-platformio-udev.rules", diff --git a/platformio/home/rpc/handlers/app.py b/platformio/home/rpc/handlers/app.py index 4b6195e4b1..2aee2f602a 100644 --- a/platformio/home/rpc/handlers/app.py +++ b/platformio/home/rpc/handlers/app.py @@ -35,7 +35,7 @@ def load_state(): with app.State( app.resolve_state_path("core_dir", "homestate.json"), lock=True ) as state: - storage = state.get("storage", {}) + storage = state.get("storage", {}) # type: ignore # base data caller_id = app.get_session_var("caller_id") @@ -56,13 +56,11 @@ def load_state(): storage["projectsDir"] = storage["coreSettings"]["projects_dir"]["value"] # skip non-existing recent projects - storage["recentProjects"] = list( - set( - str(Path(p).resolve()) - for p in storage.get("recentProjects", []) - if is_platformio_project(p) - ) - ) + storage["recentProjects"] = { + str(Path(p).resolve()) + for p in storage.get("recentProjects", []) + if is_platformio_project(p) + } state["storage"] = storage state.modified = False # skip saving extra fields @@ -79,7 +77,7 @@ def save_state(state): ) as s: s.clear() s.update(state) - storage = s.get("storage", {}) + storage = s.get("storage", {}) # type: ignore for k in AppRPC.IGNORE_STORAGE_KEYS: if k in storage: del storage[k] diff --git a/platformio/home/rpc/handlers/ide.py b/platformio/home/rpc/handlers/ide.py index 643ee0c596..2142151edd 100644 --- a/platformio/home/rpc/handlers/ide.py +++ b/platformio/home/rpc/handlers/ide.py @@ -17,7 +17,7 @@ from ajsonrpc.core import JSONRPC20DispatchException -from platformio.compat import aio_get_running_loop +from platformio.compat import aio_get_running_loop # type: ignore from platformio.home.rpc.handlers.base import BaseRPCHandler diff --git a/platformio/home/rpc/handlers/misc.py b/platformio/home/rpc/handlers/misc.py index ab2508a4dc..ed177283d2 100644 --- a/platformio/home/rpc/handlers/misc.py +++ b/platformio/home/rpc/handlers/misc.py @@ -16,7 +16,7 @@ import time from platformio.cache import ContentCache -from platformio.compat import aio_create_task +from platformio.compat import aio_create_task # type: ignore from platformio.home.rpc.handlers.base import BaseRPCHandler from platformio.home.rpc.handlers.os import OSRPC diff --git a/platformio/home/rpc/handlers/os.py b/platformio/home/rpc/handlers/os.py index b8dcfc9bfc..bc53e2b45c 100644 --- a/platformio/home/rpc/handlers/os.py +++ b/platformio/home/rpc/handlers/os.py @@ -63,9 +63,9 @@ async def fetch_content(cls, url, data=None, headers=None, cache_valid=None): cls._http_session = HTTPAsyncSession() if data: - r = await cls._http_session.post(url, data=data, headers=headers) + r = await cls._http_session.post(url, data=data, headers=headers) # type: ignore else: - r = await cls._http_session.get(url, headers=headers) + r = await cls._http_session.get(url, headers=headers) # type: ignore r.raise_for_status() result = r.text diff --git a/platformio/home/rpc/handlers/piocore.py b/platformio/home/rpc/handlers/piocore.py index b09338e51b..820d4cf858 100644 --- a/platformio/home/rpc/handlers/piocore.py +++ b/platformio/home/rpc/handlers/piocore.py @@ -24,10 +24,10 @@ from ajsonrpc.core import JSONRPC20DispatchException from platformio import __main__, __version__, app, fs, proc, util +from platformio.compat import aio_create_task # type: ignore +from platformio.compat import aio_get_running_loop # type: ignore from platformio.compat import ( IS_WINDOWS, - aio_create_task, - aio_get_running_loop, aio_to_thread, get_locale_encoding, is_bytes, @@ -96,7 +96,7 @@ def get_value_and_reset(self): return result -@util.memoized(expire="60s") +@util.memoized(expire="60s") # type: ignore def get_core_fullpath(): return proc.where_is_program("platformio" + (".exe" if IS_WINDOWS else "")) @@ -119,7 +119,7 @@ async def exec(self, args, options=None): get_core_fullpath(), *args, stdin=None, - **options.get("spawn", {}), + **options.get("spawn", {}), # type: ignore ) await exit_future transport.close() @@ -134,7 +134,7 @@ def _on_exec_data_received(self, exec_options, pipe, data): if not notification_method: return aio_create_task( - self.factory.notify_clients( + self.factory.notify_clients( # type: ignore method=notification_method, params=[data], actor="frontend", @@ -145,10 +145,10 @@ def _on_exec_data_received(self, exec_options, pipe, data): def setup_multithreading_std_streams(): if isinstance(sys.stdout, MultiThreadingStdStream): return - PIOCoreRPC.thread_stdout = MultiThreadingStdStream(sys.stdout) - PIOCoreRPC.thread_stderr = MultiThreadingStdStream(sys.stderr) - sys.stdout = PIOCoreRPC.thread_stdout - sys.stderr = PIOCoreRPC.thread_stderr + PIOCoreRPC.thread_stdout = MultiThreadingStdStream(sys.stdout) # type: ignore + PIOCoreRPC.thread_stderr = MultiThreadingStdStream(sys.stderr) # type: ignore + sys.stdout = PIOCoreRPC.thread_stdout # type: ignore + sys.stderr = PIOCoreRPC.thread_stderr # type: ignore @staticmethod async def call(args, options=None): @@ -192,8 +192,8 @@ def _thread_safe_call(args, cwd): with fs.cd(cwd): exit_code = __main__.main(["-c"] + args) return ( - PIOCoreRPC.thread_stdout.get_value_and_reset(), - PIOCoreRPC.thread_stderr.get_value_and_reset(), + PIOCoreRPC.thread_stdout.get_value_and_reset(), # type: ignore + PIOCoreRPC.thread_stderr.get_value_and_reset(), # type: ignore exit_code, ) diff --git a/platformio/home/rpc/handlers/platform.py b/platformio/home/rpc/handlers/platform.py index 34daf5405a..bbe9b523d4 100644 --- a/platformio/home/rpc/handlers/platform.py +++ b/platformio/home/rpc/handlers/platform.py @@ -31,7 +31,7 @@ async def fetch_platforms(self, search_query=None, page=0, force_installed=False ) } - search_result = await self.factory.manager.dispatcher["registry.call_client"]( + search_result = await self.factory.manager.dispatcher["registry.call_client"]( # type: ignore method="list_packages", query=search_query, qualifiers={ @@ -72,7 +72,7 @@ def _matchSearchQuery(p): items = [] pm = PlatformPackageManager() - for pkg in pm.get_installed(): + for pkg in pm.get_installed(): # type: ignore p = PlatformFactory.new(pkg) if search_query and not _matchSearchQuery(p): continue @@ -91,7 +91,7 @@ def _matchSearchQuery(p): async def fetch_boards(self, platform_spec): spec = PackageSpec(platform_spec) if spec.owner: - return await self.factory.manager.dispatcher["registry.call_client"]( + return await self.factory.manager.dispatcher["registry.call_client"]( # type: ignore method="get_package", typex="platform", owner=spec.owner, @@ -111,7 +111,7 @@ def _load_installed_boards(platform_spec): async def fetch_examples(self, platform_spec): spec = PackageSpec(platform_spec) if spec.owner: - return await self.factory.manager.dispatcher["registry.call_client"]( + return await self.factory.manager.dispatcher["registry.call_client"]( # type: ignore method="get_package", typex="platform", owner=spec.owner, diff --git a/platformio/home/rpc/handlers/project.py b/platformio/home/rpc/handlers/project.py index 817bb21058..b70c443d35 100644 --- a/platformio/home/rpc/handlers/project.py +++ b/platformio/home/rpc/handlers/project.py @@ -84,17 +84,17 @@ def _get_project_data(): data = {"boards": [], "envLibdepsDirs": [], "libExtraDirs": []} config = ProjectConfig() data["envs"] = config.envs() - data["description"] = config.get("platformio", "description") - data["libExtraDirs"].extend(config.get("platformio", "lib_extra_dirs", [])) + data["description"] = config.get("platformio", "description") # type: ignore + data["libExtraDirs"].extend(config.get("platformio", "lib_extra_dirs", [])) # type: ignore libdeps_dir = config.get("platformio", "libdeps_dir") for section in config.sections(): if not section.startswith("env:"): continue - data["envLibdepsDirs"].append(os.path.join(libdeps_dir, section[4:])) + data["envLibdepsDirs"].append(os.path.join(libdeps_dir, section[4:])) # type: ignore if config.has_option(section, "board"): data["boards"].append(config.get(section, "board")) - data["libExtraDirs"].extend(config.get(section, "lib_extra_dirs", [])) + data["libExtraDirs"].extend(config.get(section, "lib_extra_dirs", [])) # type: ignore # skip non existing folders and resolve full path for key in ("envLibdepsDirs", "libExtraDirs"): @@ -154,7 +154,7 @@ def _path_to_name(path): def get_project_examples(): result = [] pm = PlatformPackageManager() - for pkg in pm.get_installed(): + for pkg in pm.get_installed(): # type: ignore examples_dir = os.path.join(pkg.path, "examples") if not os.path.isdir(examples_dir): continue @@ -247,9 +247,9 @@ async def import_arduino(board, use_arduino_libs, arduino_project_dir): with fs.cd(project_dir): config = ProjectConfig() src_dir = config.get("platformio", "src_dir") - if os.path.isdir(src_dir): + if os.path.isdir(src_dir): # type: ignore fs.rmtree(src_dir) - shutil.copytree(arduino_project_dir, src_dir, symlinks=True) + shutil.copytree(arduino_project_dir, src_dir, symlinks=True) # type: ignore return project_dir @staticmethod @@ -289,7 +289,7 @@ async def init_v2(self, configuration, options=None): args.extend(["--ide", ide]) if configuration.get("example"): - await self.factory.notify_clients( + await self.factory.notify_clients( # type: ignore method=options.get("stdoutNotificationMethod"), params=["Copying example files...\n"], actor="frontend", @@ -298,7 +298,7 @@ async def init_v2(self, configuration, options=None): else: args.extend(self._pre_init_empty(configuration)) - return await self.factory.manager.dispatcher["core.exec"](args, options=options) + return await self.factory.manager.dispatcher["core.exec"](args, options=options) # type: ignore @staticmethod def _pre_init_empty(configuration): @@ -334,7 +334,7 @@ async def _pre_init_example(self, configuration, project_dir): if not p.parent.is_dir(): p.parent.mkdir(parents=True) p.write_text( - await self.factory.manager.dispatcher["os.request_content"]( + await self.factory.manager.dispatcher["os.request_content"]( # type: ignore item["url"] ), encoding="utf-8", @@ -352,7 +352,7 @@ def configuration(project_dir, env): # frameworks frameworks = [] - for name in config.get(f"env:{env}", "framework", []): + for name in config.get(f"env:{env}", "framework", []): # type: ignore if name not in platform.frameworks: continue f_pkg_name = platform.frameworks[name].get("package") @@ -363,28 +363,28 @@ def configuration(project_dir, env): continue f_manifest = platform.pm.load_manifest(f_pkg) frameworks.append( - dict( - name=name, - title=f_manifest.get("title"), - version=str(f_pkg.metadata.version), - ) + { + "name": name, + "title": f_manifest.get("title"), + "version": str(f_pkg.metadata.version), + } ) - return dict( - platform=dict( - ownername=( - platform_pkg.metadata.spec.owner - if platform_pkg.metadata.spec + return { + "platform": { + "ownername": ( + platform_pkg.metadata.spec.owner # type: ignore + if platform_pkg.metadata.spec # type: ignore else None ), - name=platform.name, - title=platform.title, - version=str(platform_pkg.metadata.version), - ), - board=( - platform.board_config(board_id).get_brief_data() + "name": platform.name, + "title": platform.title, + "version": str(platform_pkg.metadata.version), # type: ignore + }, + "board": ( + platform.board_config(board_id).get_brief_data() # type: ignore if board_id else None ), - frameworks=frameworks or None, - ) + "frameworks": frameworks or None, + } diff --git a/platformio/home/rpc/server.py b/platformio/home/rpc/server.py index ab7c13dad2..b391ceb1d2 100644 --- a/platformio/home/rpc/server.py +++ b/platformio/home/rpc/server.py @@ -21,7 +21,7 @@ from ajsonrpc.manager import AsyncJSONRPCResponseManager, JSONRPC20Response from starlette.endpoints import WebSocketEndpoint -from platformio.compat import aio_create_task, aio_get_running_loop +from platformio.compat import aio_create_task, aio_get_running_loop # type: ignore from platformio.http import InternetConnectionError from platformio.proc import force_exit @@ -98,13 +98,13 @@ def __call__(self, *args, **kwargs): class WebSocketJSONRPCServer(WebSocketEndpoint): encoding = "text" - factory: WebSocketJSONRPCServerFactory = None + factory: WebSocketJSONRPCServerFactory = None # type: ignore async def on_connect(self, websocket): await websocket.accept() qs = parse_qs(self.scope.get("query_string", b"")) actors = qs.get(b"actor") - self.factory.on_client_connect( # pylint: disable=no-member + self.factory.on_client_connect( # type: ignore websocket, actor=actors[0].decode() if actors else None ) @@ -112,20 +112,20 @@ async def on_receive(self, websocket, data): aio_create_task(self._handle_rpc(websocket, data)) async def on_disconnect(self, websocket, close_code): - self.factory.on_client_disconnect(websocket) # pylint: disable=no-member + self.factory.on_client_disconnect(websocket) # type: ignore async def _handle_rpc(self, websocket, data): - # pylint: disable=no-member + # type: ignore response = await self.factory.manager.get_response_for_payload(data) - if response.error and response.error.data: - click.secho("Error: %s" % response.error.data, fg="red", err=True) - if InternetConnectionError.MESSAGE in response.error.data: + if response.error and response.error.data: # type: ignore + click.secho("Error: %s" % response.error.data, fg="red", err=True) # type: ignore + if InternetConnectionError.MESSAGE in response.error.data: # type: ignore response = JSONRPC20Response( - id=response.id, + id=response.id, # type: ignore error=JSONRPC20Error( code=4008, message="No Internet Connection", - data=response.error.data, + data=response.error.data, # type: ignore ), ) - await websocket.send_text(self.factory.manager.serialize(response.body)) + await websocket.send_text(self.factory.manager.serialize(response.body)) # type: ignore diff --git a/platformio/home/run.py b/platformio/home/run.py index df3fa47e1f..3eea8322f3 100644 --- a/platformio/home/run.py +++ b/platformio/home/run.py @@ -24,7 +24,7 @@ from starlette.staticfiles import StaticFiles from starlette.status import HTTP_403_FORBIDDEN -from platformio.compat import aio_get_running_loop +from platformio.compat import aio_get_running_loop # type: ignore from platformio.exception import PlatformioException from platformio.home.rpc.handlers.account import AccountRPC from platformio.home.rpc.handlers.app import AppRPC @@ -63,7 +63,7 @@ async def protected_page(_): def run_server(host, port, no_open, shutdown_timeout, home_url): contrib_dir = get_core_package_dir("contrib-piohome") - if not os.path.isdir(contrib_dir): + if not os.path.isdir(contrib_dir): # type: ignore raise PlatformioException("Invalid path to PIO Home Contrib") ws_rpc_factory = WebSocketJSONRPCServerFactory(shutdown_timeout) diff --git a/platformio/http.py b/platformio/http.py index 3c77ff32a6..a435c5d916 100644 --- a/platformio/http.py +++ b/platformio/http.py @@ -51,7 +51,7 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.headers.update({"User-Agent": app.get_user_agent()}) try: - self.verify = app.get_setting("enable_proxy_strict_ssl") + self.verify = app.get_setting("enable_proxy_strict_ssl") # type: ignore except PlatformioException: self.verify = True @@ -109,7 +109,7 @@ def __del__(self): return try: self._session.close() - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except pass self._session = None @@ -187,7 +187,7 @@ def _parse_json_response(response, expected_codes=(200, 201, 202)): # -@util.memoized(expire="10s") +@util.memoized(expire="10s") # type: ignore def _internet_on(): timeout = 2 use_proxy = is_proxy_set() @@ -202,7 +202,7 @@ def _internet_on(): s = socket.create_connection((host, 80)) s.close() return True - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except pass # falling back to HTTPs, issue #4980 diff --git a/platformio/maintenance.py b/platformio/maintenance.py index 45b4e5c95c..0bbd78e333 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -110,9 +110,9 @@ def _appstate_migration(_): app.set_state_item( "created_at", int( - state_stat.st_birthtime + state_stat.st_birthtime # type: ignore if hasattr(state_stat, "st_birthtime") - else state_stat.st_ctime + else state_stat.st_ctime # type: ignore ), ) return True diff --git a/platformio/package/commands/exec.py b/platformio/package/commands/exec.py index 849a9320ce..e8a1315911 100644 --- a/platformio/package/commands/exec.py +++ b/platformio/package/commands/exec.py @@ -47,7 +47,7 @@ def package_exec_cmd(obj, package, call, args): click.echo( "Using %s package" - % click.style("%s@%s" % (pkg.metadata.name, pkg.metadata.version), fg="cyan") + % click.style("%s@%s" % (pkg.metadata.name, pkg.metadata.version), fg="cyan") # type: ignore ) inject_pkg_to_environ(pkg) @@ -61,7 +61,7 @@ def package_exec_cmd(obj, package, call, args): result = None try: - run_options = dict(shell=call is not None, env=os.environ) + run_options = {"shell": call is not None, "env": os.environ} force_click_stream = (obj or {}).get("force_click_stream") if force_click_stream: run_options.update(stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -81,7 +81,7 @@ def find_pkg_by_executable(executable): exes = [executable] if IS_WINDOWS and not executable.endswith(".exe"): exes.append(f"{executable}.exe") - for pkg in ToolPackageManager().get_installed(): + for pkg in ToolPackageManager().get_installed(): # type: ignore for exe in exes: if os.path.exists(os.path.join(pkg.path, exe)) or os.path.exists( os.path.join(pkg.path, "bin", exe) @@ -105,5 +105,5 @@ def inject_pkg_to_environ(pkg): lib_path_key = "DYLD_LIBRARY_PATH" if IS_MACOS else "LD_LIBRARY_PATH" lib_paths = [lib_dir] if os.environ.get(lib_path_key): - lib_paths.append(os.environ.get(lib_path_key)) + lib_paths.append(os.environ.get(lib_path_key)) # type: ignore os.environ[lib_path_key] = os.pathsep.join(lib_paths) diff --git a/platformio/package/commands/install.py b/platformio/package/commands/install.py index 675c229c52..681794394e 100644 --- a/platformio/package/commands/install.py +++ b/platformio/package/commands/install.py @@ -256,7 +256,7 @@ def _install_project_env_libraries(project_env, options): ) # install dependencies from the private libraries - for pkg in private_lm.get_installed(): + for pkg in private_lm.get_installed(): # type: ignore _install_project_private_library_deps(pkg, private_lm, env_lm, options) return not already_up_to_date diff --git a/platformio/package/commands/outdated.py b/platformio/package/commands/outdated.py index 769c937466..a2f2939230 100644 --- a/platformio/package/commands/outdated.py +++ b/platformio/package/commands/outdated.py @@ -50,7 +50,7 @@ def check(self): def is_outdated(self): if not self.outdated: self.check() - return self.outdated.is_outdated(allow_incompatible=self.pm.pkg_type != "tool") + return self.outdated.is_outdated(allow_incompatible=self.pm.pkg_type != "tool") # type: ignore @click.command("outdated", short_help="Check for outdated packages") @@ -176,7 +176,7 @@ def find_platform_candidates(config, environments): pkg = pm.get_package(spec) if not pkg: continue - result.append(dict(env=env, pm=pm, pkg=pkg, spec=spec)) + result.append({"env": env, "pm": pm, "pkg": pkg, "spec": spec}) return result @@ -185,12 +185,12 @@ def find_platform_dependency_candidates(env): p = PlatformFactory.from_env(env) for pkg in p.get_installed_packages(): result.append( - dict( - env=env, - pm=p.pm, - pkg=pkg, - spec=p.get_package_spec(pkg.metadata.name), - ) + { + "env": env, + "pm": p.pm, + "pkg": pkg, + "spec": p.get_package_spec(pkg.metadata.name), + } ) return sorted(result, key=lambda item: item["pkg"].metadata.name) @@ -212,5 +212,5 @@ def find_library_candidates(config, environments): pkg = pm.get_package(spec) if not pkg: continue - result.append(dict(env=env, pm=pm, pkg=pkg, spec=spec)) + result.append({"env": env, "pm": pm, "pkg": pkg, "spec": spec}) return sorted(result, key=lambda item: item["pkg"].metadata.name) diff --git a/platformio/package/commands/publish.py b/platformio/package/commands/publish.py index 9d495b61b0..7a5a12ff24 100644 --- a/platformio/package/commands/publish.py +++ b/platformio/package/commands/publish.py @@ -38,7 +38,7 @@ def validate_datetime(ctx, param, value): # pylint: disable=unused-argument try: datetime.strptime(value, "%Y-%m-%d %H:%M:%S") except ValueError as exc: - raise click.BadParameter(exc) + raise click.BadParameter(exc) from exc # type: ignore return value @@ -57,7 +57,7 @@ def validate_datetime(ctx, param, value): # pylint: disable=unused-argument @click.option( "--type", "typex", - type=click.Choice(list(PackageType.items().values())), + type=click.Choice(list(PackageType.items().values())), # type: ignore help="Custom package type", ) @click.option( @@ -95,7 +95,7 @@ def package_publish_cmd( # pylint: disable=too-many-arguments,too-many-position and PackageType.from_archive(package) ) archive_path = None - with tempfile.TemporaryDirectory() as tmp_dir: # pylint: disable=no-member + with tempfile.TemporaryDirectory() as tmp_dir: # type: ignore # publish .tar.gz instantly without repacking if do_not_pack: archive_path = package @@ -108,8 +108,8 @@ def package_publish_cmd( # pylint: disable=too-many-arguments,too-many-position manifest = ManifestSchema().load_manifest( ManifestParserFactory.new_from_archive(archive_path).as_dict() ) - name = manifest.get("name") - version = manifest.get("version") + name = manifest.get("name") # type: ignore + version = manifest.get("version") # type: ignore data = [ ("Type:", typex), ("Owner:", owner), @@ -117,15 +117,15 @@ def package_publish_cmd( # pylint: disable=too-many-arguments,too-many-position ("Version:", version), ("Size:", fs.humanize_file_size(os.path.getsize(archive_path))), ] - if manifest.get("system"): - data.insert(len(data) - 1, ("System:", ", ".join(manifest.get("system")))) + if manifest.get("system"): # type: ignore + data.insert(len(data) - 1, ("System:", ", ".join(manifest.get("system")))) # type: ignore click.echo(tabulate(data, tablefmt="plain")) # check files containing non-ascii chars check_archive_file_names(archive_path) # look for duplicates - check_package_duplicates(owner, typex, name, version, manifest.get("system")) + check_package_duplicates(owner, typex, name, version, manifest.get("system")) # type: ignore if not no_interactive: click.confirm( @@ -171,7 +171,7 @@ def check_package_duplicates( found = False items = ( RegistryClient() - .list_packages(qualifiers=dict(types=[type], names=[name])) + .list_packages(qualifiers={"types": [type], "names": [name]}) .get("items") ) if not items: diff --git a/platformio/package/commands/show.py b/platformio/package/commands/show.py index 5be6790ca0..3f62228f0e 100644 --- a/platformio/package/commands/show.py +++ b/platformio/package/commands/show.py @@ -30,7 +30,7 @@ "-t", "--type", "pkg_type", - type=click.Choice(list(PackageType.items().values())), + type=click.Choice(list(PackageType.items().values())), # type: ignore help="Package type", ) def package_show_cmd(spec, pkg_type): diff --git a/platformio/package/commands/unpublish.py b/platformio/package/commands/unpublish.py index 7d0e633e92..80bd9c98a1 100644 --- a/platformio/package/commands/unpublish.py +++ b/platformio/package/commands/unpublish.py @@ -25,7 +25,7 @@ ) @click.option( "--type", - type=click.Choice(list(PackageType.items().values())), + type=click.Choice(list(PackageType.items().values())), # type: ignore default="library", help="Package type, default is set to `library`", ) diff --git a/platformio/package/download.py b/platformio/package/download.py index d8ad564869..6450f7d8c8 100644 --- a/platformio/package/download.py +++ b/platformio/package/download.py @@ -62,17 +62,17 @@ def get_filepath(self): return self._destination def get_lmtime(self): - return self._http_response.headers.get("last-modified") + return self._http_response.headers.get("last-modified") # type: ignore def get_size(self): - if "content-length" not in self._http_response.headers: + if "content-length" not in self._http_response.headers: # type: ignore return -1 - return int(self._http_response.headers["content-length"]) + return int(self._http_response.headers["content-length"]) # type: ignore def start(self, with_progress=True, silent=False): label = "Downloading" file_size = self.get_size() - itercontent = self._http_response.iter_content( + itercontent = self._http_response.iter_content( # type: ignore chunk_size=io.DEFAULT_BUFFER_SIZE ) try: @@ -104,15 +104,15 @@ def start(self, with_progress=True, silent=False): iterable=itercontent, label=label, update_min_steps=min( - 256 * 1024, file_size / 100 + 256 * 1024, file_size // 100 ), # every 256Kb or less ) as pb: for chunk in pb: pb.update(len(chunk)) fp.write(chunk) finally: - self._http_response.close() - self._http_session.close() + self._http_response.close() # type: ignore + self._http_session.close() # type: ignore if self.get_lmtime(): self._preserve_filemtime(self.get_lmtime()) @@ -156,10 +156,10 @@ def verify(self, checksum=None): return True def _preserve_filemtime(self, lmdate): - lmtime = mktime(parsedate(lmdate)) + lmtime = mktime(parsedate(lmdate)) # type: ignore fs.change_filemtime(self._destination, lmtime) def __del__(self): - self._http_session.close() + self._http_session.close() # type: ignore if self._http_response: - self._http_response.close() + self._http_response.close() # type: ignore diff --git a/platformio/package/lockfile.py b/platformio/package/lockfile.py index bc2a4347ca..08f22582d7 100644 --- a/platformio/package/lockfile.py +++ b/platformio/package/lockfile.py @@ -57,7 +57,7 @@ def _lock(self): if time() - os.path.getmtime(self._lock_path) > 10: try: os.remove(self._lock_path) - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except pass else: raise LockFileExists @@ -67,10 +67,10 @@ def _lock(self): ) try: if LOCKFILE_CURRENT_INTERFACE == LOCKFILE_INTERFACE_FCNTL: - fcntl.flock(self._fp.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) + fcntl.flock(self._fp.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) # type: ignore elif LOCKFILE_CURRENT_INTERFACE == LOCKFILE_INTERFACE_MSVCRT: msvcrt.locking( # pylint: disable=used-before-assignment - self._fp.fileno(), msvcrt.LK_NBLCK, 1 + self._fp.fileno(), msvcrt.LK_NBLCK, 1 # type: ignore ) except (BlockingIOError, IOError) as exc: self._fp.close() @@ -82,9 +82,9 @@ def _unlock(self): if not self._fp: return if LOCKFILE_CURRENT_INTERFACE == LOCKFILE_INTERFACE_FCNTL: - fcntl.flock(self._fp.fileno(), fcntl.LOCK_UN) + fcntl.flock(self._fp.fileno(), fcntl.LOCK_UN) # type: ignore elif LOCKFILE_CURRENT_INTERFACE == LOCKFILE_INTERFACE_MSVCRT: - msvcrt.locking(self._fp.fileno(), msvcrt.LK_UNLCK, 1) + msvcrt.locking(self._fp.fileno(), msvcrt.LK_UNLCK, 1) # type: ignore self._fp.close() self._fp = None @@ -104,7 +104,7 @@ def release(self): if os.path.exists(self._lock_path): try: os.remove(self._lock_path) - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except pass def __enter__(self): diff --git a/platformio/package/manager/_download.py b/platformio/package/manager/_download.py index bf844980ee..fc742d088a 100644 --- a/platformio/package/manager/_download.py +++ b/platformio/package/manager/_download.py @@ -32,11 +32,11 @@ def compute_download_path(self, *args): request_hash = hashlib.new("sha1") for arg in args: request_hash.update(compat.hashlib_encode_data(arg)) - dl_path = os.path.join(self.get_download_dir(), request_hash.hexdigest()) + dl_path = os.path.join(self.get_download_dir(), request_hash.hexdigest()) # type: ignore return dl_path def get_download_usagedb_path(self): - return os.path.join(self.get_download_dir(), "usage.db") + return os.path.join(self.get_download_dir(), "usage.db") # type: ignore def set_download_utime(self, path, utime=None): with app.State(self.get_download_usagedb_path(), lock=True) as state: @@ -50,19 +50,19 @@ def cleanup_expired_downloads(self, _=None): if state[fname] > (time.time() - self.DOWNLOAD_CACHE_EXPIRE): continue del state[fname] - dl_path = os.path.join(self.get_download_dir(), fname) + dl_path = os.path.join(self.get_download_dir(), fname) # type: ignore if os.path.isfile(dl_path): os.remove(dl_path) def download(self, url, checksum=None): - silent = not self.log.isEnabledFor(logging.INFO) + silent = not self.log.isEnabledFor(logging.INFO) # type: ignore dl_path = self.compute_download_path(url, checksum or "") if os.path.isfile(dl_path): self.set_download_utime(dl_path) return dl_path with_progress = not app.is_disabled_progressbar() - tmp_fd, tmp_path = tempfile.mkstemp(dir=self.get_download_dir()) + tmp_fd, tmp_path = tempfile.mkstemp(dir=self.get_download_dir()) # type: ignore try: with LockFile(dl_path): try: @@ -79,7 +79,7 @@ def download(self, url, checksum=None): except IOError: raise_error = True if raise_error: - self.log.error( + self.log.error( # type: ignore click.style( "Error: Please read https://bit.ly/package-manager-ioerror", fg="red", @@ -87,14 +87,14 @@ def download(self, url, checksum=None): ) raise exc if checksum: - fd.verify(checksum) + fd.verify(checksum) # type: ignore os.close(tmp_fd) - os.rename(tmp_path, dl_path) + os.rename(tmp_path, dl_path) # type: ignore finally: if os.path.isfile(tmp_path): os.close(tmp_fd) os.remove(tmp_path) assert os.path.isfile(dl_path) - self.set_download_utime(dl_path) + self.set_download_utime(dl_path) # type: ignore return dl_path diff --git a/platformio/package/manager/_install.py b/platformio/package/manager/_install.py index 12c116d1c8..795be13634 100644 --- a/platformio/package/manager/_install.py +++ b/platformio/package/manager/_install.py @@ -43,22 +43,22 @@ def unpack(src, dst): def install(self, spec, skip_dependencies=False, force=False): try: - self.lock() + self.lock() # type: ignore pkg = self._install(spec, skip_dependencies=skip_dependencies, force=force) - self.memcache_reset() - self.cleanup_expired_downloads() + self.memcache_reset() # type: ignore + self.cleanup_expired_downloads() # type: ignore return pkg finally: - self.unlock() + self.unlock() # type: ignore def _install( self, spec, skip_dependencies=False, force=False, - compatibility: PackageCompatibility = None, + compatibility: PackageCompatibility = None, # type: ignore ): - spec = self.ensure_spec(spec) + spec = self.ensure_spec(spec) # type: ignore # avoid circle dependencies if not self._INSTALL_HISTORY: @@ -67,36 +67,36 @@ def _install( return self._INSTALL_HISTORY[spec] # check if package is already installed - pkg = self.get_package(spec) + pkg = self.get_package(spec) # type: ignore # if a forced installation if pkg and force: - self.uninstall(pkg) + self.uninstall(pkg) # type: ignore pkg = None if pkg: # avoid RecursionError for circular_dependencies self._INSTALL_HISTORY[spec] = pkg - self.log.debug( + self.log.debug( # type: ignore click.style( "{name}@{version} is already installed".format( - **pkg.metadata.as_dict() + **pkg.metadata.as_dict() # type: ignore ), fg="yellow", ) ) # ensure package dependencies are installed if not skip_dependencies: - self.install_dependencies(pkg, print_header=False) + self.install_dependencies(pkg, print_header=False) # type: ignore return pkg - self.log.info("Installing %s" % click.style(spec.humanize(), fg="cyan")) + self.log.info("Installing %s" % click.style(spec.humanize(), fg="cyan")) # type: ignore if spec.external: - pkg = self.install_from_uri(spec.uri, spec) + pkg = self.install_from_uri(spec.uri, spec) # type: ignore else: - pkg = self.install_from_registry( + pkg = self.install_from_registry( # type: ignore spec, search_qualifiers=( compatibility.to_search_qualifiers( @@ -113,69 +113,69 @@ def _install( % (spec.humanize(), util.get_systype()) ) - self.call_pkg_script(pkg, "postinstall") + self.call_pkg_script(pkg, "postinstall") # type: ignore - self.log.info( + self.log.info( # type: ignore click.style( "{name}@{version} has been installed!".format(**pkg.metadata.as_dict()), fg="green", ) ) - self.memcache_reset() + self.memcache_reset() # type: ignore # avoid RecursionError for circular_dependencies self._INSTALL_HISTORY[spec] = pkg if not skip_dependencies: - self.install_dependencies(pkg) + self.install_dependencies(pkg) # type: ignore return pkg def install_dependencies(self, pkg, print_header=True): assert isinstance(pkg, PackageItem) - dependencies = self.get_pkg_dependencies(pkg) + dependencies = self.get_pkg_dependencies(pkg) # type: ignore if not dependencies: return if print_header: - self.log.info("Resolving dependencies...") + self.log.info("Resolving dependencies...") # type: ignore for dependency in dependencies: try: - self.install_dependency(dependency) + self.install_dependency(dependency) # type: ignore except UnknownPackageError: if dependency.get("owner"): - self.log.warning( + self.log.warning( # type: ignore click.style( "Warning! Could not install `%s` dependency " - "for the`%s` package" % (dependency, pkg.metadata.name), + "for the`%s` package" % (dependency, pkg.metadata.name), # type: ignore fg="yellow", ) ) def install_dependency(self, dependency): - dependency_compatibility = PackageCompatibility.from_dependency(dependency) - if self.compatibility and not dependency_compatibility.is_compatible( - self.compatibility + dependency_compatibility = PackageCompatibility.from_dependency(dependency) # type: ignore + if self.compatibility and not dependency_compatibility.is_compatible( # type: ignore + self.compatibility # type: ignore ): - self.log.debug( + self.log.debug( # type: ignore click.style( "Skip incompatible `%s` dependency with `%s`" - % (dependency, self.compatibility), + % (dependency, self.compatibility), # type: ignore fg="yellow", ) ) return None return self._install( - spec=self.dependency_to_spec(dependency), - compatibility=dependency_compatibility, + spec=self.dependency_to_spec(dependency), # type: ignore + compatibility=dependency_compatibility, # type: ignore ) def install_from_uri(self, uri, spec, checksum=None): - spec = self.ensure_spec(spec) + spec = self.ensure_spec(spec) # type: ignore if spec.symlink: - return self.install_symlink(spec) + return self.install_symlink(spec) # type: ignore - tmp_dir = tempfile.mkdtemp(prefix="pkg-installing-", dir=self.get_tmp_dir()) + tmp_dir = tempfile.mkdtemp(prefix="pkg-installing-", dir=self.get_tmp_dir()) # type: ignore vcs = None try: if uri.startswith("file://"): @@ -186,66 +186,66 @@ def install_from_uri(self, uri, spec, checksum=None): fs.rmtree(tmp_dir) shutil.copytree(_uri, tmp_dir, symlinks=True) elif uri.startswith(("http://", "https://")): - dl_path = self.download(uri, checksum) + dl_path = self.download(uri, checksum) # type: ignore assert os.path.isfile(dl_path) self.unpack(dl_path, tmp_dir) else: vcs = VCSClientFactory.new(tmp_dir, uri) assert vcs.export() - root_dir = self.find_pkg_root(tmp_dir, spec) + root_dir = self.find_pkg_root(tmp_dir, spec) # type: ignore pkg_item = PackageItem( root_dir, - self.build_metadata( - root_dir, spec, vcs.get_current_revision() if vcs else None + self.build_metadata( # type: ignore + root_dir, spec, vcs.get_current_revision() if vcs else None # type: ignore ), ) - pkg_item.dump_meta() + pkg_item.dump_meta() # type: ignore return self._install_tmp_pkg(pkg_item) finally: if os.path.isdir(tmp_dir): try: fs.rmtree(tmp_dir) - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except pass def _install_tmp_pkg(self, tmp_pkg): assert isinstance(tmp_pkg, PackageItem) # validate package version and declared requirements if ( - tmp_pkg.metadata.spec.requirements - and tmp_pkg.metadata.version not in tmp_pkg.metadata.spec.requirements + tmp_pkg.metadata.spec.requirements # type: ignore + and tmp_pkg.metadata.version not in tmp_pkg.metadata.spec.requirements # type: ignore ): raise PackageException( "Package version %s doesn't satisfy requirements %s based on %s" % ( - tmp_pkg.metadata.version, - tmp_pkg.metadata.spec.requirements, + tmp_pkg.metadata.version, # type: ignore + tmp_pkg.metadata.spec.requirements, # type: ignore tmp_pkg.metadata, ) ) dst_pkg = PackageItem( - os.path.join(self.package_dir, tmp_pkg.get_safe_dirname()) + os.path.join(self.package_dir, tmp_pkg.get_safe_dirname()) # type: ignore ) # what to do with existing package? action = "overwrite" - if tmp_pkg.metadata.spec.has_custom_name(): + if tmp_pkg.metadata.spec.has_custom_name(): # type: ignore action = "overwrite" dst_pkg = PackageItem( - os.path.join(self.package_dir, tmp_pkg.metadata.spec.name) + os.path.join(self.package_dir, tmp_pkg.metadata.spec.name) # type: ignore ) elif dst_pkg.metadata: - if dst_pkg.metadata.spec.external: - if dst_pkg.metadata.spec.uri != tmp_pkg.metadata.spec.uri: + if dst_pkg.metadata.spec.external: # type: ignore + if dst_pkg.metadata.spec.uri != tmp_pkg.metadata.spec.uri: # type: ignore action = "detach-existing" elif ( - dst_pkg.metadata.version != tmp_pkg.metadata.version - or dst_pkg.metadata.spec.owner != tmp_pkg.metadata.spec.owner + dst_pkg.metadata.version != tmp_pkg.metadata.version # type: ignore + or dst_pkg.metadata.spec.owner != tmp_pkg.metadata.spec.owner # type: ignore ): action = ( "detach-existing" - if tmp_pkg.metadata.version > dst_pkg.metadata.version + if tmp_pkg.metadata.version > dst_pkg.metadata.version # type: ignore else "detach-new" ) @@ -256,17 +256,17 @@ def _cleanup_dir(path): if action == "detach-existing": target_dirname = "%s@%s" % ( tmp_pkg.get_safe_dirname(), - dst_pkg.metadata.version, + dst_pkg.metadata.version, # type: ignore ) - if dst_pkg.metadata.spec.uri: + if dst_pkg.metadata.spec.uri: # type: ignore target_dirname = "%s@src-%s" % ( tmp_pkg.get_safe_dirname(), hashlib.md5( - compat.hashlib_encode_data(dst_pkg.metadata.spec.uri) + compat.hashlib_encode_data(dst_pkg.metadata.spec.uri) # type: ignore ).hexdigest(), ) # move existing into the new place - pkg_dir = os.path.join(self.package_dir, target_dirname) + pkg_dir = os.path.join(self.package_dir, target_dirname) # type: ignore _cleanup_dir(pkg_dir) shutil.copytree(dst_pkg.path, pkg_dir, symlinks=True) # move new source to the destination location @@ -277,16 +277,16 @@ def _cleanup_dir(path): if action == "detach-new": target_dirname = "%s@%s" % ( tmp_pkg.get_safe_dirname(), - tmp_pkg.metadata.version, + tmp_pkg.metadata.version, # type: ignore ) - if tmp_pkg.metadata.spec.external: + if tmp_pkg.metadata.spec.external: # type: ignore target_dirname = "%s@src-%s" % ( tmp_pkg.get_safe_dirname(), hashlib.md5( - compat.hashlib_encode_data(tmp_pkg.metadata.spec.uri) + compat.hashlib_encode_data(tmp_pkg.metadata.spec.uri) # type: ignore ).hexdigest(), ) - pkg_dir = os.path.join(self.package_dir, target_dirname) + pkg_dir = os.path.join(self.package_dir, target_dirname) # type: ignore _cleanup_dir(pkg_dir) shutil.copytree(tmp_pkg.path, pkg_dir, symlinks=True) return PackageItem(pkg_dir) diff --git a/platformio/package/manager/_legacy.py b/platformio/package/manager/_legacy.py index 4b02a1dffd..89d649a720 100644 --- a/platformio/package/manager/_legacy.py +++ b/platformio/package/manager/_legacy.py @@ -38,24 +38,24 @@ def build_legacy_spec(self, pkg_dir): ) # fall back to a package manifest - manifest = self.load_manifest(pkg_dir) + manifest = self.load_manifest(pkg_dir) # type: ignore return PackageSpec(name=manifest.get("name")) def legacy_load_manifest(self, pkg): if not isinstance(pkg, PackageItem): assert os.path.isdir(pkg) pkg = PackageItem(pkg) - manifest = self.load_manifest(pkg) + manifest = self.load_manifest(pkg) # type: ignore manifest["__pkg_dir"] = pkg.path for key in ("name", "version"): if not manifest.get(key): manifest[key] = str(getattr(pkg.metadata, key)) - if pkg.metadata and pkg.metadata.spec and pkg.metadata.spec.external: + if pkg.metadata and pkg.metadata.spec and pkg.metadata.spec.external: # type: ignore manifest["__src_url"] = pkg.metadata.spec.uri - manifest["version"] = str(pkg.metadata.version) - if pkg.metadata and pkg.metadata.spec.owner: - manifest["ownername"] = pkg.metadata.spec.owner + manifest["version"] = str(pkg.metadata.version) # type: ignore + if pkg.metadata and pkg.metadata.spec.owner: # type: ignore + manifest["ownername"] = pkg.metadata.spec.owner # type: ignore return manifest def legacy_get_installed(self): - return [self.legacy_load_manifest(pkg) for pkg in self.get_installed()] + return [self.legacy_load_manifest(pkg) for pkg in self.get_installed()] # type: ignore diff --git a/platformio/package/manager/_registry.py b/platformio/package/manager/_registry.py index 4c339be8a7..e4a8ab4aca 100644 --- a/platformio/package/manager/_registry.py +++ b/platformio/package/manager/_registry.py @@ -36,7 +36,7 @@ def install_from_registry(self, spec, search_qualifiers=None): if not packages: raise UnknownPackageError(spec.humanize()) if len(packages) > 1: - self.print_multi_package_issue(self.log.warning, packages, spec) + self.print_multi_package_issue(self.log.warning, packages, spec) # type: ignore package, version = self.find_best_registry_version(packages, spec) if not package or not version: @@ -48,7 +48,7 @@ def install_from_registry(self, spec, search_qualifiers=None): for url, checksum in RegistryFileMirrorIterator(pkgfile["download_url"]): try: - return self.install_from_uri( + return self.install_from_uri( # type: ignore url, PackageSpec( owner=package["owner"]["username"], @@ -58,10 +58,10 @@ def install_from_registry(self, spec, search_qualifiers=None): checksum or pkgfile["checksum"]["sha256"], ) except Exception as exc: # pylint: disable=broad-except - self.log.warning( + self.log.warning( # type: ignore click.style("Warning! Package Mirror: %s" % exc, fg="yellow") ) - self.log.warning( + self.log.warning( # type: ignore click.style("Looking for another mirror...", fg="yellow") ) @@ -78,8 +78,8 @@ def search_registry_packages(self, spec, qualifiers=None): if spec.id: qualifiers["ids"] = str(spec.id) else: - qualifiers["types"] = self.pkg_type - qualifiers["names"] = spec.name.lower() + qualifiers["types"] = self.pkg_type # type: ignore + qualifiers["names"] = spec.name.lower() # type: ignore if spec.owner: qualifiers["owners"] = spec.owner.lower() return self.get_registry_client_instance().list_packages(qualifiers=qualifiers)[ @@ -91,27 +91,27 @@ def fetch_registry_package(self, spec): result = None regclient = self.get_registry_client_instance() if spec.owner and spec.name: - result = regclient.get_package(self.pkg_type, spec.owner, spec.name) + result = regclient.get_package(self.pkg_type, spec.owner, spec.name) # type: ignore if not result and (spec.id or (spec.name and not spec.owner)): packages = self.search_registry_packages(spec) if packages: result = regclient.get_package( - self.pkg_type, packages[0]["owner"]["username"], packages[0]["name"] + self.pkg_type, packages[0]["owner"]["username"], packages[0]["name"] # type: ignore ) if not result: raise UnknownPackageError(spec.humanize()) return result def reveal_registry_package_id(self, spec): - spec = self.ensure_spec(spec) + spec = self.ensure_spec(spec) # type: ignore if spec.id: return spec.id packages = self.search_registry_packages(spec) if not packages: raise UnknownPackageError(spec.humanize()) if len(packages) > 1: - self.print_multi_package_issue(self.log.warning, packages, spec) - self.log.info("") + self.print_multi_package_issue(self.log.warning, packages, spec) # type: ignore + self.log.info("") # type: ignore return packages[0]["id"] @staticmethod @@ -171,7 +171,7 @@ def get_compatible_registry_versions(self, versions, spec=None, custom_system=No if spec and spec.requirements and semver not in spec.requirements: continue if not any( - self.is_system_compatible(f.get("system"), custom_system=custom_system) + self.is_system_compatible(f.get("system"), custom_system=custom_system) # type: ignore for f in version["files"] ): continue @@ -190,8 +190,8 @@ def pick_best_registry_version(self, versions, spec=None, custom_system=None): def pick_compatible_pkg_file(self, version_files, custom_system=None): for item in version_files: - if self.is_system_compatible( - item.get("system"), custom_system=custom_system + if self.is_system_compatible( # type: ignore + item.get("system"), custom_system=custom_system # type: ignore ): return item return None diff --git a/platformio/package/manager/_symlink.py b/platformio/package/manager/_symlink.py index 33ff03f1bc..3b19122929 100644 --- a/platformio/package/manager/_symlink.py +++ b/platformio/package/manager/_symlink.py @@ -31,7 +31,7 @@ def resolve_symlink(cls, path): data = fs.load_json(path) spec = PackageSpec(**data["spec"]) assert spec.symlink - pkg_dir = spec.uri[10:] + pkg_dir = spec.uri[10:] # type: ignore if not os.path.isabs(pkg_dir): pkg_dir = os.path.normpath(os.path.join(data["cwd"], pkg_dir)) return (pkg_dir if os.path.isdir(pkg_dir) else None, spec) @@ -42,7 +42,7 @@ def get_symlinked_package(self, path): return None pkg = PackageItem(os.path.realpath(pkg_dir)) if not pkg.metadata: - pkg.metadata = self.build_metadata(pkg.path, spec) + pkg.metadata = self.build_metadata(pkg.path, spec) # type: ignore return pkg def install_symlink(self, spec): @@ -53,19 +53,19 @@ def install_symlink(self, spec): f"Can not create a symbolic link for `{pkg_dir}`, not a directory" ) link_path = os.path.join( - self.package_dir, + self.package_dir, # type: ignore "%s.pio-link" % (spec.name or os.path.basename(os.path.abspath(pkg_dir))), ) with open(link_path, mode="w", encoding="utf-8") as fp: - json.dump(dict(cwd=os.getcwd(), spec=spec.as_dict()), fp) + json.dump({"cwd": os.getcwd(), "spec": spec.as_dict()}, fp) return self.get_symlinked_package(link_path) def uninstall_symlink(self, spec): assert spec.symlink - for name in os.listdir(self.package_dir): - path = os.path.join(self.package_dir, name) + for name in os.listdir(self.package_dir): # type: ignore + path = os.path.join(self.package_dir, name) # type: ignore if not self.is_symlink(path): continue pkg = self.get_symlinked_package(path) - if pkg.metadata.spec.uri == spec.uri: + if pkg.metadata.spec.uri == spec.uri: # type: ignore os.remove(path) diff --git a/platformio/package/manager/_uninstall.py b/platformio/package/manager/_uninstall.py index b374fd0166..b00880c4ad 100644 --- a/platformio/package/manager/_uninstall.py +++ b/platformio/package/manager/_uninstall.py @@ -25,59 +25,59 @@ class PackageManagerUninstallMixin: def uninstall(self, spec, skip_dependencies=False): try: - self.lock() + self.lock() # type: ignore return self._uninstall(spec, skip_dependencies) finally: - self.unlock() + self.unlock() # type: ignore def _uninstall(self, spec, skip_dependencies=False): - pkg = self.get_package(spec) + pkg = self.get_package(spec) # type: ignore if not pkg or not pkg.metadata: raise UnknownPackageError(spec) - uninstalled_pkgs = self.memcache_get("__uninstalled_pkgs", []) + uninstalled_pkgs = self.memcache_get("__uninstalled_pkgs", []) # type: ignore if uninstalled_pkgs and pkg.path in uninstalled_pkgs: return pkg uninstalled_pkgs.append(pkg.path) - self.memcache_set("__uninstalled_pkgs", uninstalled_pkgs) + self.memcache_set("__uninstalled_pkgs", uninstalled_pkgs) # type: ignore - self.log.info( + self.log.info( # type: ignore "Removing %s @ %s" % (click.style(pkg.metadata.name, fg="cyan"), pkg.metadata.version) ) - self.call_pkg_script(pkg, "preuninstall") + self.call_pkg_script(pkg, "preuninstall") # type: ignore # firstly, remove dependencies if not skip_dependencies: - self.uninstall_dependencies(pkg) + self.uninstall_dependencies(pkg) # type: ignore if pkg.metadata.spec.symlink: - self.uninstall_symlink(pkg.metadata.spec) + self.uninstall_symlink(pkg.metadata.spec) # type: ignore elif os.path.islink(pkg.path): os.unlink(pkg.path) else: fs.rmtree(pkg.path) - self.memcache_reset() + self.memcache_reset() # type: ignore # unfix detached-package with the same name - detached_pkg = self.get_package(PackageSpec(name=pkg.metadata.name)) + detached_pkg = self.get_package(PackageSpec(name=pkg.metadata.name)) # type: ignore if ( detached_pkg and "@" in detached_pkg.path and not os.path.isdir( - os.path.join(self.package_dir, detached_pkg.get_safe_dirname()) + os.path.join(self.package_dir, detached_pkg.get_safe_dirname()) # type: ignore ) ): shutil.move( detached_pkg.path, - os.path.join(self.package_dir, detached_pkg.get_safe_dirname()), + os.path.join(self.package_dir, detached_pkg.get_safe_dirname()), # type: ignore ) - self.memcache_reset() + self.memcache_reset() # type: ignore - self.log.info( + self.log.info( # type: ignore click.style( - "{name}@{version} has been removed!".format(**pkg.metadata.as_dict()), + "{name}@{version} has been removed!".format(**pkg.metadata.as_dict()), # type: ignore fg="green", ) ) @@ -86,12 +86,12 @@ def _uninstall(self, spec, skip_dependencies=False): def uninstall_dependencies(self, pkg): assert isinstance(pkg, PackageItem) - dependencies = self.get_pkg_dependencies(pkg) + dependencies = self.get_pkg_dependencies(pkg) # type: ignore if not dependencies: return - self.log.info("Removing dependencies...") + self.log.info("Removing dependencies...") # type: ignore for dependency in dependencies: - pkg = self.get_package(self.dependency_to_spec(dependency)) + pkg = self.get_package(self.dependency_to_spec(dependency)) # type: ignore if not pkg: continue self._uninstall(pkg) diff --git a/platformio/package/manager/_update.py b/platformio/package/manager/_update.py index 353e9e45c0..1370a274c5 100644 --- a/platformio/package/manager/_update.py +++ b/platformio/package/manager/_update.py @@ -43,17 +43,19 @@ def outdated(self, pkg, spec=None): latest = None wanted = None + assert pkg.metadata.spec is not None if pkg.metadata.spec.external: latest = self._fetch_vcs_latest_version(pkg) else: try: - reg_pkg = self.fetch_registry_package(pkg.metadata.spec) + assert self.fetch_registry_package is not None # type: ignore + reg_pkg = self.fetch_registry_package(pkg.metadata.spec) # type: ignore latest = ( - self.pick_best_registry_version(reg_pkg["versions"]) or {} + self.pick_best_registry_version(reg_pkg["versions"]) or {} # type: ignore ).get("name") if spec: wanted = ( - self.pick_best_registry_version(reg_pkg["versions"], spec) or {} + self.pick_best_registry_version(reg_pkg["versions"], spec) or {} # type: ignore ).get("name") if not wanted: # wrong library latest = None @@ -78,7 +80,7 @@ def _fetch_vcs_latest_version(self, pkg): return None return str( - self.build_metadata( + self.build_metadata( # type: ignore pkg.path, pkg.metadata.spec, vcs_revision=vcs_revision ).version ) @@ -89,44 +91,44 @@ def update( to_spec=None, skip_dependencies=False, ): - pkg = self.get_package(from_spec) + pkg = self.get_package(from_spec) # type: ignore if not pkg or not pkg.metadata: raise UnknownPackageError(from_spec) outdated = self.outdated(pkg, to_spec) if not outdated.is_outdated(allow_incompatible=False): - self.log.debug( + self.log.debug( # type: ignore click.style( "{name}@{version} is already up-to-date".format( - **pkg.metadata.as_dict() + **pkg.metadata.as_dict() # type: ignore ), fg="yellow", ) ) return pkg - self.log.info( + self.log.info( # type: ignore "Updating %s @ %s" - % (click.style(pkg.metadata.name, fg="cyan"), pkg.metadata.version) + % (click.style(pkg.metadata.name, fg="cyan"), pkg.metadata.version) # type: ignore ) try: - self.lock() + self.lock() # type: ignore return self._update(pkg, outdated, skip_dependencies) finally: - self.unlock() + self.unlock() # type: ignore def _update(self, pkg, outdated, skip_dependencies=False): if pkg.metadata.spec.external: - vcs = VCSClientFactory.new(pkg.path, pkg.metadata.spec.uri) + vcs = VCSClientFactory.new(pkg.path, pkg.metadata.spec.uri) # type: ignore assert vcs.update() - pkg.metadata.version = self._fetch_vcs_latest_version(pkg) + pkg.metadata.version = self._fetch_vcs_latest_version(pkg) # type: ignore pkg.dump_meta() return pkg # uninstall existing version - self.uninstall(pkg, skip_dependencies=True) + self.uninstall(pkg, skip_dependencies=True) # type: ignore - return self.install( + return self.install( # type: ignore PackageSpec( id=pkg.metadata.spec.id, owner=pkg.metadata.spec.owner, diff --git a/platformio/package/manager/base.py b/platformio/package/manager/base.py index a4ad07bafb..9334049d64 100644 --- a/platformio/package/manager/base.py +++ b/platformio/package/manager/base.py @@ -262,20 +262,20 @@ def get_package(self, spec): return spec spec = self.ensure_spec(spec) best = None - for pkg in self.get_installed(): + for pkg in self.get_installed(): # type: ignore if not self.test_pkg_spec(pkg, spec): continue assert isinstance(pkg.metadata.version, semantic_version.Version) if spec.requirements and pkg.metadata.version not in spec.requirements: continue - if not best or (pkg.metadata.version > best.metadata.version): + if not best or (pkg.metadata.version > best.metadata.version): # type: ignore best = pkg return best @staticmethod def test_pkg_spec(pkg, spec): # "id" mismatch - if spec.id and spec.id != pkg.metadata.spec.id: + if spec.id and spec.id != pkg.metadata.spec.id: # type: ignore return False # external "URL" mismatch @@ -286,27 +286,27 @@ def test_pkg_spec(pkg, spec): spec.uri.startswith("file://") and os.path.abspath(pkg.path) == os.path.abspath(spec.uri[7:]), spec.uri.startswith("symlink://") - and os.path.abspath(pkg.path) == os.path.abspath(spec.uri[10:]), + and os.path.abspath(pkg.path) == os.path.abspath(spec.uri[10:]), # type: ignore ] if any(check_conds): return True - if spec.uri != pkg.metadata.spec.uri: + if spec.uri != pkg.metadata.spec.uri: # type: ignore return False # "owner" mismatch elif spec.owner and not ci_strings_are_equal( - spec.owner, pkg.metadata.spec.owner + spec.owner, pkg.metadata.spec.owner # type: ignore ): return False # "name" mismatch - elif not spec.id and not ci_strings_are_equal(spec.name, pkg.metadata.name): + elif not spec.id and not ci_strings_are_equal(spec.name, pkg.metadata.name): # type: ignore return False return True def get_pkg_dependencies(self, pkg): - return self.load_manifest(pkg).get("dependencies") + return self.load_manifest(pkg).get("dependencies") # type: ignore @staticmethod def dependency_to_spec(dependency): diff --git a/platformio/package/manager/core.py b/platformio/package/manager/core.py index f4e0f50ea4..2527459a11 100644 --- a/platformio/package/manager/core.py +++ b/platformio/package/manager/core.py @@ -46,7 +46,7 @@ def get_core_package_dir(name, spec=None, auto_install=True): return None assert pm.install(spec) remove_unnecessary_core_packages() - return pm.get_package(spec).path + return pm.get_package(spec).path # type: ignore def update_core_packages(): @@ -71,10 +71,10 @@ def remove_unnecessary_core_packages(dry_run=False): pkg = pm.get_package(spec) if not pkg: continue - # pylint: disable=no-member - best_pkg_versions[pkg.metadata.name] = pkg.metadata.version + # type: ignore + best_pkg_versions[pkg.metadata.name] = pkg.metadata.version # type: ignore - for pkg in pm.get_installed(): + for pkg in pm.get_installed(): # type: ignore skip_conds = [ os.path.isfile(os.path.join(pkg.path, ".piokeep")), pkg.metadata.spec.owner != "platformio", diff --git a/platformio/package/manager/library.py b/platformio/package/manager/library.py index 6babfc9cc8..96f20c3b51 100644 --- a/platformio/package/manager/library.py +++ b/platformio/package/manager/library.py @@ -49,26 +49,20 @@ def find_pkg_root(self, path, spec): with open( os.path.join(root_dir, "library.json"), mode="w", encoding="utf8" ) as fp: - json.dump( - dict( - name=spec.name, - version=self.generate_rand_version(), - ), - fp, - indent=2, - ) + json.dump({ + "name": spec.name, + "version": self.generate_rand_version(), + }, fp) return root_dir @staticmethod def find_library_root(path): - root_dir_signs = set(["include", "Include", "inc", "Inc", "src", "Src"]) - root_file_signs = set( - [ - "conanfile.py", # Conan-based library - "CMakeLists.txt", # CMake-based library - ] - ) + root_dir_signs = {"include", "Include", "inc", "Inc", "src", "Src"} + root_file_signs = { + "conanfile.py", # Conan-based library + "CMakeLists.txt", # CMake-based library + } for root, dirs, files in os.walk(path): if not files and len(dirs) == 1: continue @@ -92,7 +86,7 @@ def install_dependency(self, dependency): return None @staticmethod - @util.memoized(expire="60s") + @util.memoized(expire="60s") # type: ignore def get_builtin_libs(storage_names=None): # pylint: disable=import-outside-toplevel from platformio.package.manager.platform import PlatformPackageManager @@ -100,7 +94,7 @@ def get_builtin_libs(storage_names=None): items = [] storage_names = storage_names or [] pm = PlatformPackageManager() - for pkg in pm.get_installed(): + for pkg in pm.get_installed(): # type: ignore p = PlatformFactory.new(pkg) for storage in p.get_lib_storages(): if storage_names and storage["name"] not in storage_names: diff --git a/platformio/package/manager/platform.py b/platformio/package/manager/platform.py index 4baafdc2c0..c2ea697c39 100644 --- a/platformio/package/manager/platform.py +++ b/platformio/package/manager/platform.py @@ -104,10 +104,12 @@ def update( # pylint: disable=arguments-differ p.update_packages() return pkg - @util.memoized(expire="5s") + @util.memoized(expire="5s") # type: ignore def get_installed_boards(self): boards = [] - for pkg in self.get_installed(): + installed = self.get_installed() + assert installed is not None + for pkg in installed: p = PlatformFactory.new(pkg) for config in p.get_boards().values(): board = config.get_brief_data() @@ -155,13 +157,15 @@ def remove_unnecessary_platform_packages(dry_run=False): candidates = [] required = set() core_packages = get_installed_core_packages() - for platform in PlatformPackageManager().get_installed(): + installed = PlatformPackageManager().get_installed() + assert installed is not None + for platform in installed: p = PlatformFactory.new(platform) for pkg in p.get_installed_packages(with_optional_versions=True): required.add(pkg) pm = ToolPackageManager() - for pkg in pm.get_installed(): + for pkg in pm.get_installed(): # type: ignore skip_conds = [ pkg.metadata.spec.uri, os.path.isfile(os.path.join(pkg.path, ".piokeep")), diff --git a/platformio/package/manifest/parser.py b/platformio/package/manifest/parser.py index 7694c8a859..511084aee0 100644 --- a/platformio/package/manifest/parser.py +++ b/platformio/package/manifest/parser.py @@ -40,14 +40,14 @@ def items(cls): @classmethod def from_uri(cls, uri): - for t in sorted(cls.items().values()): + for t in sorted(cls.items().values()): # type: ignore if uri.endswith(t): return t return None @classmethod def from_dir(cls, path): - for t in sorted(cls.items().values()): + for t in sorted(cls.items().values()): # type: ignore if os.path.isfile(os.path.join(path, t)): return t return None @@ -63,7 +63,7 @@ def read_manifest_contents(path): return fp.read() except UnicodeDecodeError as exc: last_err = exc - raise last_err + raise last_err # type: ignore @classmethod def new_from_file(cls, path, remote_url=False): @@ -114,11 +114,11 @@ def new_from_url(remote_url): def new_from_archive(path): assert path.endswith("tar.gz") with tarfile.open(path, mode="r:gz") as tf: - for t in sorted(ManifestFileType.items().values()): + for t in sorted(ManifestFileType.items().values()): # type: ignore for member in (t, "./" + t): try: return ManifestParserFactory.new( - tf.extractfile(member).read().decode(), t + tf.extractfile(member).read().decode(), t # type: ignore ) except KeyError: pass @@ -133,7 +133,7 @@ def new( # pylint: disable=redefined-builtin inspect.isclass(cls) and issubclass(cls, BaseManifestParser) and cls != BaseManifestParser - and cls.manifest_type == type + and cls.manifest_type == type # type: ignore ): return cls(contents, remote_url, package_dir) raise UnknownManifestError("Unknown manifest file type %s" % type) @@ -273,11 +273,11 @@ def parse_examples_from_dir(package_dir): if is_platformio_project(root): last_pio_project = root - result[last_pio_project] = dict( - name=os.path.relpath(root, examples_dir), - base=os.path.relpath(root, package_dir), - files=files, - ) + result[last_pio_project] = { + "name": os.path.relpath(root, examples_dir), + "base": os.path.relpath(root, package_dir), + "files": files, + } continue if last_pio_project: if root.startswith(last_pio_project): @@ -293,15 +293,15 @@ def parse_examples_from_dir(package_dir): matched_files = [f for f in files if f.endswith(allowed_exts)] if not matched_files: continue - result[root] = dict( - name=( + result[root] = { + "name": ( "Examples" if root == examples_dir else os.path.relpath(root, examples_dir) ), - base=os.path.relpath(root, package_dir), - files=matched_files, - ) + "base": os.path.relpath(root, package_dir), + "files": matched_files, + } result = list(result.values()) @@ -393,9 +393,9 @@ def _parse_dependencies(raw): for name, version in raw.items(): if "/" in name: owner, name = name.split("/", 1) - result.append(dict(owner=owner, name=name, version=version)) + result.append({"owner": owner, "name": name, "version": version}) else: - result.append(dict(name=name, version=version)) + result.append({"name": name, "version": version}) return result if isinstance(raw, list): @@ -443,7 +443,7 @@ def _parse_authors(self, raw): name, email = self.parse_author_name_and_email(author) if not name: continue - result.append(self.cleanup_author(dict(name=name, email=email))) + result.append(self.cleanup_author({"name": name, "email": email})) return result @staticmethod @@ -456,7 +456,7 @@ def _parse_license(raw): def _parse_dependencies(raw): if isinstance(raw, dict): return [ - dict(name=name, version=version, frameworks=["mbed"]) + {"name": name, "version": version, "frameworks": ["mbed"]} for name, version in raw.items() ] raise ManifestParserError("Invalid dependencies format, should be a dictionary") @@ -472,15 +472,15 @@ def parse(self, contents): if repository and repository["url"] == homepage: homepage = None data.update( - dict( - frameworks=["arduino"], - homepage=homepage, - repository=repository or None, - description=self._parse_description(data), - platforms=self._parse_platforms(data) or None, - keywords=self._parse_keywords(data) or None, - export=self._parse_export(), - ) + { + "frameworks": ["arduino"], + "homepage": homepage, + "repository": repository or None, + "description": self._parse_description(data), + "platforms": self._parse_platforms(data) or None, + "keywords": self._parse_keywords(data) or None, + "export": self._parse_export(), + } ) if "includes" in data: data["headers"] = self.str_to_list(data["includes"], sep=",", unique=True) @@ -565,7 +565,7 @@ def _parse_authors(self, properties): name, email = self.parse_author_name_and_email(author) if not name: continue - authors.append(self.cleanup_author(dict(name=name, email=email))) + authors.append(self.cleanup_author({"name": name, "email": email})) for author in properties.get("maintainer", "").split(","): name, email = self.parse_author_name_and_email(author) if not name: @@ -580,9 +580,7 @@ def _parse_authors(self, properties): if not item.get("email") and email and "@" in email: item["email"] = email if not found: - authors.append( - self.cleanup_author(dict(name=name, email=email, maintainer=True)) - ) + authors.append(self.cleanup_author({"name": name, "email": email, "maintainer": True})) return authors def _parse_repository(self, properties): @@ -590,21 +588,21 @@ def _parse_repository(self, properties): url_attrs = urlparse(self.remote_url) repo_path_tokens = url_attrs.path[1:].split("/")[:-1] if "github" in url_attrs.netloc: - return dict( - type="git", - url="https://github.com/" + "/".join(repo_path_tokens[:2]), - ) + return { + "type": "git", + "url": "https://github.com/" + "/".join(repo_path_tokens[:2]), + } if "raw" in repo_path_tokens: - return dict( - type="git", - url="https://%s/%s" + return { + "type": "git", + "url": "https://%s/%s" % ( url_attrs.netloc, "/".join(repo_path_tokens[: repo_path_tokens.index("raw")]), ), - ) + } if properties.get("url", "").startswith("https://github.com"): - return dict(type="git", url=properties["url"]) + return {"type": "git", "url": properties["url"]} return None def _parse_export(self): @@ -620,7 +618,7 @@ def _parse_export(self): or None ) if include: - return dict(include=[include]) + return {"include": [include]} return None @staticmethod @@ -632,15 +630,13 @@ def _parse_dependencies(raw): continue if item.endswith(")") and "(" in item: name, version = item.split("(") - result.append( - dict( - name=name.strip(), - version=version[:-1].strip(), - frameworks=["arduino"], - ) - ) + result.append({ + "name": name.strip(), + "version": version[:-1].strip(), + "frameworks": ["arduino"], + }) else: - result.append(dict(name=item, frameworks=["arduino"])) + result.append({"name": item, "frameworks": ["arduino"]}) return result @@ -711,7 +707,7 @@ def _parse_homepage(data): def _parse_repository(data): if isinstance(data.get("repository", {}), dict): return data - data["repository"] = dict(type="git", url=str(data["repository"])) + data["repository"] = {"type": "git", "url": str(data["repository"])} if data["repository"]["url"].startswith(("github:", "gitlab:", "bitbucket:")): data["repository"]["url"] = "https://{0}.com/{1}".format( *(data["repository"]["url"].split(":", 1)) diff --git a/platformio/package/manifest/schema.py b/platformio/package/manifest/schema.py index d38b9c9f4d..c0a09e0e7e 100644 --- a/platformio/package/manifest/schema.py +++ b/platformio/package/manifest/schema.py @@ -29,7 +29,7 @@ class BaseSchema(Schema): class Meta: - unknown = marshmallow.EXCLUDE # pylint: disable=no-member + unknown = marshmallow.EXCLUDE # type: ignore def load_manifest(self, data): return self.load(data) @@ -62,7 +62,7 @@ def _deserialize( # pylint: disable=arguments-differ return super()._deserialize(value, attr, data, **kwargs) except ValidationError as exc: if exc.data: - exc.data = [item for item in exc.data if item is not None] + exc.data = [item for item in exc.data if item is not None] # type: ignore raise exc @@ -113,8 +113,8 @@ class DependencySchema(StrictSchema): class ExportSchema(BaseSchema): - include = StrictListField(fields.Str) - exclude = StrictListField(fields.Str) + include = StrictListField(fields.Str) # type: ignore + exclude = StrictListField(fields.Str) # type: ignore class ExampleSchema(StrictSchema): @@ -129,7 +129,7 @@ class ExampleSchema(StrictSchema): ], ) base = fields.Str(required=True) - files = StrictListField(fields.Str, required=True) + files = StrictListField(fields.Str, required=True) # type: ignore # Fields @@ -170,12 +170,12 @@ class ManifestSchema(BaseSchema): dependencies = fields.Nested(DependencySchema, many=True) scripts = fields.Dict( keys=fields.Str(validate=validate.OneOf(["postinstall", "preuninstall"])), - values=ScriptField(), + values=ScriptField(), # type: ignore ) # library.json export = fields.Nested(ExportSchema) - examples = fields.Nested(ExampleSchema, many=True) + examples = fields.Nested(ExampleSchema, many=True) # type: ignore downloadUrl = fields.Url(validate=validate.Length(min=1, max=255)) keywords = StrictListField( @@ -256,7 +256,7 @@ def validate_license(self, value): raise ValidationError( "Could not load SPDX licenses for validation" ) from exc - known_ids = set(item.get("licenseId") for item in spdx.get("licenses", [])) + known_ids = {item.get("licenseId") for item in spdx.get("licenses", [])} if value in known_ids: return True # parse license expression @@ -274,7 +274,7 @@ def validate_license(self, value): ) @staticmethod - @memoized(expire="1h") + @memoized(expire="1h") # type: ignore def load_spdx_licenses(): version = "3.26.0" spdx_data_url = ( diff --git a/platformio/package/meta.py b/platformio/package/meta.py index e4398cffbe..0c6ff745cb 100644 --- a/platformio/package/meta.py +++ b/platformio/package/meta.py @@ -54,7 +54,7 @@ def from_archive(cls, path): assert path.endswith("tar.gz") manifest_map = cls.get_manifest_map() with tarfile.open(path, mode="r:gz") as tf: - for t in sorted(cls.items().values()): + for t in sorted(cls.items().values()): # type: ignore for manifest in manifest_map[t]: try: if tf.getmember(manifest): @@ -227,8 +227,8 @@ def __eq__(self, other): ) def __hash__(self): - return crc32( - hashlib_encode_data( + return crc32( # type: ignore + hashlib_encode_data( # type: ignore "%s-%s-%s-%s-%s" % (self.owner, self.id, self.name, self.requirements, self.uri) ) @@ -284,13 +284,13 @@ def has_custom_name(self): return self._name_is_custom def as_dict(self): - return dict( - owner=self.owner, - id=self.id, - name=self.name, - requirements=str(self.requirements) if self.requirements else None, - uri=self.uri, - ) + return { + "owner": self.owner, + "id": self.id, + "name": self.name, + "requirements": str(self.requirements) if self.requirements else None, + "uri": self.uri, + } def as_dependency(self): if self.uri: @@ -479,12 +479,12 @@ def version(self, value): ) def as_dict(self): - return dict( - type=self.type, - name=self.name, - version=str(self.version), - spec=self.spec.as_dict() if self.spec else None, - ) + return { + "type": self.type, + "name": self.name, + "version": str(self.version), + "spec": self.spec.as_dict() if self.spec else None, + } def dump(self, path): with open(path, mode="w", encoding="utf8") as fp: @@ -560,4 +560,5 @@ def dump_meta(self): if os.path.isdir(location): break assert location + assert self.metadata is not None return self.metadata.dump(os.path.join(location, self.METAFILE_NAME)) diff --git a/platformio/package/pack.py b/platformio/package/pack.py index 0170ee3d00..87f33e7f6c 100644 --- a/platformio/package/pack.py +++ b/platformio/package/pack.py @@ -33,7 +33,7 @@ class PackagePacker: - INCLUDE_DEFAULT = list(ManifestFileType.items().values()) + [ + INCLUDE_DEFAULT = list(ManifestFileType.items().values()) + [ # type: ignore "README", "README.md", "README.rst", @@ -166,9 +166,9 @@ def pack(self, dst=None): self.manifest_parser = ManifestParserFactory.new_from_dir(src) manifest = ManifestSchema().load_manifest(self.manifest_parser.as_dict()) filename = self.get_archive_name( - manifest["name"], - manifest["version"], - manifest["system"][0] if "system" in manifest else None, + manifest["name"], # type: ignore + manifest["version"], # type: ignore + manifest["system"][0] if "system" in manifest else None, # type: ignore ) if not dst: @@ -188,7 +188,7 @@ def find_source_root(self, src): else ManifestParserFactory.new_from_url(self.manifest_uri) ) manifest = ManifestSchema().load_manifest(mp.as_dict()) - include = manifest.get("export", {}).get("include", []) + include = manifest.get("export", {}).get("include", []) # type: ignore if len(include) == 1: if not os.path.isdir(os.path.join(src, include[0])): raise PackageException( @@ -204,8 +204,8 @@ def find_source_root(self, src): return src def create_tarball(self, src, dst, manifest): - include = manifest.get("export", {}).get("include") - exclude = manifest.get("export", {}).get("exclude") + include = manifest.get("export", {}).get("include") # type: ignore + exclude = manifest.get("export", {}).get("exclude") # type: ignore # remap root if ( include diff --git a/platformio/package/unpack.py b/platformio/package/unpack.py index ea140ae930..237112bab7 100644 --- a/platformio/package/unpack.py +++ b/platformio/package/unpack.py @@ -116,7 +116,7 @@ def preserve_permissions(item, dest_dir): def preserve_mtime(item, dest_dir): fs.change_filemtime( os.path.join(dest_dir, item.filename), - mktime(tuple(item.date_time) + tuple([0, 0, 0])), + mktime(item.date_time + (0, 0, 0)) ) @staticmethod @@ -195,7 +195,7 @@ def unpack( with click.progressbar( items, label=label, - update_min_steps=min(50, len(items) / 100), # every 50 files or less + update_min_steps=min(50, len(items) // 100), # every 50 files or less ) as pb: for item in pb: self._archiver.extract_item(item, dest_dir) diff --git a/platformio/package/vcsclient.py b/platformio/package/vcsclient.py index 67348391c5..999f7f7004 100644 --- a/platformio/package/vcsclient.py +++ b/platformio/package/vcsclient.py @@ -78,7 +78,7 @@ def check_client(self): @property def storage_dir(self): - return os.path.join(self.src_dir, "." + self.command) + return os.path.join(self.src_dir, "." + self.command) # type: ignore def export(self): raise NotImplementedError @@ -116,7 +116,7 @@ def get_cmd_output(self, args, **kwargs): kwargs["cwd"] = self.src_dir result = proc.exec_command(args, **kwargs) if result["returncode"] == 0: - return result["out"].strip() + return result["out"].strip() # type: ignore raise VCSBaseException( "VCS: Could not receive an output from `%s` command (%s)" % (args, result) ) @@ -139,7 +139,7 @@ def configure(cls): result = proc.exec_command([cls.command, "--exec-path"]) if result["returncode"] != 0: return False - path = result["out"].strip() + path = result["out"].strip() # type: ignore if path: proc.append_env_path("PATH", path) return True @@ -232,7 +232,7 @@ def export(self): args = ["clone"] if self.tag: args.extend(["--updaterev", self.tag]) - args.extend([self.remote_url, self.src_dir]) + args.extend([self.remote_url, self.src_dir]) # type: ignore return self.run_cmd(args) def update(self): @@ -255,7 +255,7 @@ def export(self): args = ["checkout"] if self.tag: args.extend(["--revision", self.tag]) - args.extend([self.remote_url, self.src_dir]) + args.extend([self.remote_url, self.src_dir]) # type: ignore return self.run_cmd(args) def update(self): diff --git a/platformio/platform/_packages.py b/platformio/platform/_packages.py index 2a3aa49045..2786d4378b 100644 --- a/platformio/platform/_packages.py +++ b/platformio/platform/_packages.py @@ -18,15 +18,15 @@ class PlatformPackagesMixin: def get_package_spec(self, name, version=None): return PackageSpec( - owner=self.packages[name].get("owner"), + owner=self.packages[name].get("owner"), # type: ignore name=name, - requirements=version or self.packages[name].get("version"), + requirements=version or self.packages[name].get("version"), # type: ignore ) def get_package(self, name, spec=None): if not name: return None - return self.pm.get_package(spec or self.get_package_spec(name)) + return self.pm.get_package(spec or self.get_package_spec(name)) # type: ignore def get_package_dir(self, name): pkg = self.get_package(name) @@ -38,7 +38,7 @@ def get_package_version(self, name): def get_installed_packages(self, with_optional=True, with_optional_versions=False): result = [] - for name, options in dict(sorted(self.packages.items())).items(): + for name, options in dict(sorted(self.packages.items())).items(): # type: ignore if not with_optional and options.get("optional"): continue versions = [options.get("version")] @@ -54,7 +54,7 @@ def get_installed_packages(self, with_optional=True, with_optional_versions=Fals def dump_used_packages(self): result = [] - for name, options in self.packages.items(): + for name, options in self.packages.items(): # type: ignore if options.get("optional"): continue pkg = self.get_package(name) @@ -67,26 +67,27 @@ def dump_used_packages(self): return result def install_package(self, name, spec=None, force=False): - return self.pm.install(spec or self.get_package_spec(name), force=force) + return self.pm.install(spec or self.get_package_spec(name), force=force) # type: ignore def install_required_packages(self, force=False): - for name, options in self.packages.items(): + assert self.pm is not None # type: ignore + for name, options in self.packages.items(): # type: ignore if options.get("optional"): continue self.install_package(name, force=force) def uninstall_packages(self): - for pkg in self.get_installed_packages(): - self.pm.uninstall(pkg) + for pkg in self.get_installed_packages(): # type: ignore + self.pm.uninstall(pkg) # type: ignore def update_packages(self): - for pkg in self.get_installed_packages(): - self.pm.update(pkg, to_spec=self.get_package_spec(pkg.metadata.name)) + for pkg in self.get_installed_packages(): # type: ignore + self.pm.update(pkg, to_spec=self.get_package_spec(pkg.metadata.name)) # type: ignore def are_outdated_packages(self): - for pkg in self.get_installed_packages(): - if self.pm.outdated( - pkg, self.get_package_spec(pkg.metadata.name) + for pkg in self.get_installed_packages(): # type: ignore + if self.pm.outdated( # type: ignore + pkg, self.get_package_spec(pkg.metadata.name) # type: ignore ).is_outdated(allow_incompatible=False): return True return False diff --git a/platformio/platform/_run.py b/platformio/platform/_run.py index 81d697f50d..3bbe3aa6ad 100644 --- a/platformio/platform/_run.py +++ b/platformio/platform/_run.py @@ -35,7 +35,7 @@ class PlatformRunMixin: def encode_scons_arg(value): if isinstance(value, (list, tuple, dict)): value = json.dumps(value) - return base64.urlsafe_b64encode(hashlib_encode_data(value)).decode() + return base64.urlsafe_b64encode(hashlib_encode_data(value)).decode() # type: ignore @staticmethod def decode_scons_arg(data): @@ -50,17 +50,17 @@ def run( # pylint: disable=too-many-arguments,too-many-positional-arguments assert isinstance(variables, dict) assert isinstance(targets, list) - self.ensure_engine_compatible() + self.ensure_engine_compatible() # type: ignore self.silent = silent self.verbose = verbose or app.get_setting("force_verbose") if "build_script" not in variables: - variables["build_script"] = self.get_build_script() + variables["build_script"] = self.get_build_script() # type: ignore if not os.path.isfile(variables["build_script"]): raise BuildScriptNotFound(variables["build_script"]) - telemetry.log_platform_run(self, self.config, variables["pioenv"], targets) + telemetry.log_platform_run(self, self.config, variables["pioenv"], targets) # type: ignore result = self._run_scons(variables, targets, jobs) assert "returncode" in result @@ -71,7 +71,7 @@ def _run_scons(self, variables, targets, jobs): scons_dir = get_core_package_dir("tool-scons") args = [ proc.get_pythonexe_path(), - os.path.join(scons_dir, "scons.py"), + os.path.join(scons_dir, "scons.py"), # type: ignore "-Q", "--warn=no-no-parallel-support", "--jobs", @@ -81,7 +81,7 @@ def _run_scons(self, variables, targets, jobs): ] args.append("PIOVERBOSE=%d" % int(self.verbose)) # pylint: disable=protected-access - args.append("ISATTY=%d" % int(click._compat.isatty(sys.stdout))) + args.append("ISATTY=%d" % int(click._compat.isatty(sys.stdout))) # type: ignore # encode and append variables for key, value in variables.items(): args.append("%s=%s" % (key.upper(), self.encode_scons_arg(value))) @@ -103,7 +103,7 @@ def _run_scons(self, variables, targets, jobs): args, stdout=sys.stdout, stderr=sys.stderr, stdin=sys.stdin ) - if click._compat.isatty(sys.stdout): + if click._compat.isatty(sys.stdout): # type: ignore def _write_and_flush(stream, data): try: diff --git a/platformio/platform/base.py b/platformio/platform/base.py index 0d2d57a9dc..23e84fa321 100644 --- a/platformio/platform/base.py +++ b/platformio/platform/base.py @@ -237,4 +237,4 @@ def get_lib_storages(self): continue storages[libcore_dir] = "%s-core-%s" % (opts["package"], item) - return [dict(name=name, path=path) for path, name in storages.items()] + return [{"name": name, "path": path} for path, name in storages.items()] diff --git a/platformio/platform/board.py b/platformio/platform/board.py index 78d48943e6..e61d1c0dec 100644 --- a/platformio/platform/board.py +++ b/platformio/platform/board.py @@ -30,7 +30,7 @@ def __init__(self, manifest_path): self._manifest = fs.load_json(manifest_path) except InvalidJSONFile as exc: raise InvalidBoardManifest(manifest_path) from exc - if not set(["name", "url", "vendor"]) <= set(self._manifest): + if not {"name", "url", "vendor"} <= set(self._manifest): raise UserSideException( "Please specify name, url and vendor fields for " + manifest_path ) @@ -125,7 +125,7 @@ def get_debug_tool_name(self, custom=None): return tool_name raise DebugInvalidOptionsError( "Unknown debug tool `%s`. Please use one of `%s` or `custom`" - % (tool_name, ", ".join(sorted(list(debug_tools)))) + % (tool_name, ", ".join(sorted(debug_tools))) ) # automatically select best tool @@ -137,7 +137,7 @@ def get_debug_tool_name(self, custom=None): data["onboard"].append(key) data["external"].append(key) - for key, value in data.items(): + for _key, value in data.items(): if not value: continue return sorted(value)[0] diff --git a/platformio/platform/factory.py b/platformio/platform/factory.py index 42c3432bde..1adbddd6b2 100644 --- a/platformio/platform/factory.py +++ b/platformio/platform/factory.py @@ -49,17 +49,17 @@ def new(cls, pkg_or_spec, autoinstall=False) -> base.PlatformBase: platform_name = None if isinstance(pkg_or_spec, PackageItem): platform_dir = pkg_or_spec.path - platform_name = pkg_or_spec.metadata.name + platform_name = pkg_or_spec.metadata.name # type: ignore elif isinstance(pkg_or_spec, (str, bytes)) and os.path.isdir(pkg_or_spec): platform_dir = pkg_or_spec else: pkg = PlatformPackageManager().get_package(pkg_or_spec) if pkg: platform_dir = pkg.path - platform_name = pkg.metadata.name + platform_name = pkg.metadata.name # type: ignore if not platform_dir or not os.path.isfile( - os.path.join(platform_dir, "platform.json") + os.path.join(platform_dir, "platform.json") # type: ignore ): if autoinstall: return cls.new( @@ -70,15 +70,15 @@ def new(cls, pkg_or_spec, autoinstall=False) -> base.PlatformBase: raise UnknownPlatform(pkg_or_spec) if not platform_name: - platform_name = fs.load_json(os.path.join(platform_dir, "platform.json"))[ + platform_name = fs.load_json(os.path.join(platform_dir, "platform.json"))[ # type: ignore "name" ] platform_cls = None - if os.path.isfile(os.path.join(platform_dir, "platform.py")): + if os.path.isfile(os.path.join(platform_dir, "platform.py")): # type: ignore platform_cls = getattr( cls.load_platform_module( - platform_name, os.path.join(platform_dir, "platform.py") + platform_name, os.path.join(platform_dir, "platform.py") # type: ignore ), cls.get_clsname(platform_name), ) @@ -87,7 +87,7 @@ def new(cls, pkg_or_spec, autoinstall=False) -> base.PlatformBase: str(cls.get_clsname(platform_name)), (base.PlatformBase,), {} ) - _instance = platform_cls(os.path.join(platform_dir, "platform.json")) + _instance = platform_cls(os.path.join(platform_dir, "platform.json")) # type: ignore assert isinstance(_instance, base.PlatformBase) return _instance diff --git a/platformio/proc.py b/platformio/proc.py index 707245a138..3d011e0026 100644 --- a/platformio/proc.py +++ b/platformio/proc.py @@ -107,24 +107,24 @@ def do_reading(self): def exec_command(*args, **kwargs): result = {"out": None, "err": None, "returncode": None} - default = dict(stdout=subprocess.PIPE, stderr=subprocess.PIPE) + default = {"stdout": subprocess.PIPE, "stderr": subprocess.PIPE} default.update(kwargs) kwargs = default with subprocess.Popen(*args, **kwargs) as p: try: - result["out"], result["err"] = p.communicate() - result["returncode"] = p.returncode + result["out"], result["err"] = p.communicate() # type: ignore + result["returncode"] = p.returncode # type: ignore except KeyboardInterrupt as exc: raise exception.AbortedByUser() from exc finally: for s in ("stdout", "stderr"): if isinstance(kwargs[s], AsyncPipeBase): - kwargs[s].close() # pylint: disable=no-member + kwargs[s].close() # type: ignore for s in ("stdout", "stderr"): if isinstance(kwargs[s], AsyncPipeBase): - result[s[3:]] = kwargs[s].get_buffer() # pylint: disable=no-member + result[s[3:]] = kwargs[s].get_buffer() # type: ignore for key, value in result.items(): if isinstance(value, bytes): @@ -171,8 +171,8 @@ def get_pythonexe_path(): def copy_pythonpath_to_osenv(): _PYTHONPATH = [] if "PYTHONPATH" in os.environ: - _PYTHONPATH = os.environ.get("PYTHONPATH").split(os.pathsep) - for p in os.sys.path: + _PYTHONPATH = os.environ.get("PYTHONPATH").split(os.pathsep) # type: ignore + for p in os.sys.path: # type: ignore conditions = [p not in _PYTHONPATH] if not IS_WINDOWS: conditions.append( @@ -199,8 +199,8 @@ def where_is_program(program, envpath=None): # try OS's built-in commands try: result = exec_command(["where" if IS_WINDOWS else "which", program], env=env) - if result["returncode"] == 0 and os.path.isfile(result["out"].strip()): - return result["out"].strip() + if result["returncode"] == 0 and os.path.isfile(result["out"].strip()): # type: ignore + return result["out"].strip() # type: ignore except OSError: pass diff --git a/platformio/project/commands/init.py b/platformio/project/commands/init.py index f4702eb385..be0fed5f58 100644 --- a/platformio/project/commands/init.py +++ b/platformio/project/commands/init.py @@ -104,11 +104,11 @@ def project_init_cmd( # pylint: disable=too-many-positional-arguments # resolve project dependencies if not no_install_dependencies and (environment or boards): install_project_dependencies( - options=dict( - project_dir=project_dir, - environments=[environment] if environment else [], - silent=silent, - ) + options={ + "project_dir": project_dir, + "environments": [environment] if environment else [], + "silent": silent, + } ) if environment and sample_code: diff --git a/platformio/project/commands/metadata.py b/platformio/project/commands/metadata.py index ee9f5b194c..bce01cbacd 100644 --- a/platformio/project/commands/metadata.py +++ b/platformio/project/commands/metadata.py @@ -46,10 +46,10 @@ def project_metadata_cmd(project_dir, environments, json_output, json_output_pat if not json_output: install_project_dependencies( - options=dict( - project_dir=project_dir, - environments=environments, - ) + options={ + "project_dir": project_dir, + "environments": environments, + } ) click.echo() @@ -64,6 +64,7 @@ def project_metadata_cmd(project_dir, environments, json_output, json_output_pat click.echo(json.dumps(build_metadata)) return + assert build_metadata is not None for envname, metadata in build_metadata.items(): click.echo("Environment: " + click.style(envname, fg="cyan", bold=True)) click.echo("=" * (13 + len(envname))) diff --git a/platformio/project/config.py b/platformio/project/config.py index 82b76abf09..3a27c81afd 100644 --- a/platformio/project/config.py +++ b/platformio/project/config.py @@ -50,7 +50,7 @@ class ProjectConfigBase: "PROJECT_HASH": lambda: "%s-%s" % ( os.path.basename(os.getcwd()), - hashlib.sha1(hashlib_encode_data(os.getcwd())).hexdigest()[:10], + hashlib.sha1(hashlib_encode_data(os.getcwd())).hexdigest()[:10], # type: ignore ), "UNIX_TIME": lambda: str(int(time.time())), } @@ -108,6 +108,7 @@ def read(self, path, parse_extra=True): return self._parsed.append(path) try: + assert self._parser is not None self._parser.read(path, "utf-8") except configparser.Error as exc: raise exception.InvalidProjectConfError(path, str(exc)) from exc @@ -116,7 +117,7 @@ def read(self, path, parse_extra=True): return # load extra configs - for pattern in self.get("platformio", "extra_configs", []): + for pattern in self.get("platformio", "extra_configs", []): # type: ignore if pattern.startswith("~"): pattern = fs.expanduser(pattern) for item in glob.glob(pattern, recursive=True): @@ -126,13 +127,13 @@ def _maintain_renamed_options(self): renamed_options = {} for option in ProjectOptions.values(): if option.oldnames: - renamed_options.update({name: option.name for name in option.oldnames}) + renamed_options.update(dict.fromkeys(option.oldnames, option.name)) - for section in self._parser.sections(): + for section in self._parser.sections(): # type: ignore scope = self.get_section_scope(section) if scope not in ("platformio", "env"): continue - for option in self._parser.options(section): + for option in self._parser.options(section): # type: ignore if option in renamed_options: self.warnings.append( "`%s` configuration option in section [%s] is " @@ -175,6 +176,7 @@ def walk_options(self, root_section): while extends_queue: section = extends_queue.pop() extends_done.append(section) + assert self._parser is not None if not self._parser.has_section(section): continue for option in self._parser.options(section): @@ -188,10 +190,10 @@ def options(self, section=None, env=None): result = [] assert section or env if not section: - section = "env:" + env + section = "env:" + str(env) if not self.expand_interpolations: - return self._parser.options(section) + return self._parser.options(section) # type: ignore for _, option in self.walk_options(section): if option not in result: @@ -208,6 +210,7 @@ def options(self, section=None, env=None): return result def has_option(self, section, option): + assert self._parser is not None if self._parser.has_option(section, option): return True return option in self.options(section) @@ -215,7 +218,7 @@ def has_option(self, section, option): def items(self, section=None, env=None, as_dict=False): assert section or env if not section: - section = "env:" + env + section = "env:" + str(env) if as_dict: return { option: self.get(section, option) for option in self.options(section) @@ -234,7 +237,7 @@ def set(self, section, option, value): # start multi-line value from a new line if "\n" in value and not value.startswith("\n"): value = "\n" + value - self._parser.set(section, option, value) + self._parser.set(section, option, value) # type: ignore def resolve_renamed_option(self, section, old_name): scope = self.get_section_scope(section) @@ -270,13 +273,14 @@ def _traverse_for_value(self, section, option, option_meta=None): or _option in (option_meta.oldnames or []) ) ): - return self._parser.get(_section, _option) + return self._parser.get(_section, _option) # type: ignore return MISSING def getraw( self, section, option, default=MISSING ): # pylint: disable=too-many-branches if not self.expand_interpolations: + assert self._parser is not None return self._parser.get(section, option) option_meta = self.find_option_meta(section, option) @@ -284,6 +288,7 @@ def getraw( if not option_meta: if value == MISSING: + assert self._parser is not None value = ( default if default != MISSING else self._parser.get(section, option) ) @@ -299,7 +304,7 @@ def getraw( if envvar_value and option_meta.multiple: if value == MISSING: value = "" - value += ("\n" if value else "") + envvar_value + value += ("\n" if value else "") + envvar_value # type: ignore elif envvar_value: value = envvar_value @@ -313,7 +318,7 @@ def getraw( return self._expand_interpolations(section, option, value) def _expand_interpolations(self, section, option, value): - if not value or not isinstance(value, string_types) or not "$" in value: + if not value or not isinstance(value, string_types) or "$" not in value: return value # legacy support for variables delclared without "${}" @@ -337,7 +342,7 @@ def _expand_interpolations(self, section, option, value): if not all(["${" in value, "}" in value]): return value return self.VARTPL_RE.sub( - lambda match: self._re_interpolation_handler(section, option, match), value + lambda match: self._re_interpolation_handler(section, option, match), value # type: ignore ) def _re_interpolation_handler(self, parent_section, parent_option, match): @@ -383,7 +388,7 @@ def get(self, section, option, default=MISSING): try: value = self.getraw(section, option, default) except configparser.Error as exc: - raise exception.InvalidProjectConfError(self.path, str(exc)) + raise exception.InvalidProjectConfError(self.path, str(exc)) from exc option_meta = self.find_option_meta(section, option) if not option_meta: @@ -401,7 +406,7 @@ def get(self, section, option, default=MISSING): raise exception.ProjectOptionValueError( "%s for `%s` option in the `%s` section (%s)" % (exc.format_message(), option, section, option_meta.description) - ) + ) from exc @staticmethod def cast_to(value, to_type): @@ -415,7 +420,7 @@ def cast_to(value, to_type): return items if isinstance(value, (list, tuple)) else items[0] def envs(self): - return [s[4:] for s in self._parser.sections() if s.startswith("env:")] + return [s[4:] for s in self._parser.sections() if s.startswith("env:")] # type: ignore def default_envs(self): return self.get("platformio", "default_envs", []) @@ -436,7 +441,7 @@ def validate(self, envs=None, silent=False): # check envs if not known_envs: raise exception.ProjectEnvsNotAvailableError() - unknown_envs = set(list(envs or []) + self.default_envs()) - known_envs + unknown_envs = set(list(envs or []) + self.default_envs()) - known_envs # type: ignore if unknown_envs: raise exception.UnknownEnvNamesError( ", ".join(unknown_envs), ", ".join(known_envs) @@ -471,7 +476,7 @@ def lint(cls, path=None): errors = [] warnings = [] try: - config = cls.get_instance(path) + config = cls.get_instance(path) # type: ignore config.validate(silent=True) warnings = config.warnings # in case "as_tuple" fails config.as_tuple() @@ -486,7 +491,7 @@ def lint(cls, path=None): item[attr] = getattr(exc, attr) if item["type"] == "ParsingError" and hasattr(exc, "errors"): - for lineno, line in getattr(exc, "errors"): + for lineno, line in exc.errors: # type: ignore errors.append( { "type": item["type"], @@ -507,7 +512,7 @@ def get_optional_dir(self, name): PlatformIO IDE for Atom depends on platformio-node-helpers@~7.2.0 PIO Home 3.0 Project Inspection depends on it """ - return self.get("platformio", f"{name}_dir") + return self.get("platformio", f"{name}_dir") # type: ignore class ProjectConfig(ProjectConfigBase, ProjectConfigLintMixin, ProjectConfigDirsMixin): diff --git a/platformio/project/helpers.py b/platformio/project/helpers.py index 2732e6bd4d..ca99c8c873 100644 --- a/platformio/project/helpers.py +++ b/platformio/project/helpers.py @@ -77,7 +77,7 @@ def get_default_projects_dir(): buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) ctypes.windll.shell32.SHGetFolderPathW(None, 5, None, 0, buf) docs_dir = buf.value - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except if not IS_MACOS: try: docs_dir = ( @@ -92,7 +92,7 @@ def get_default_projects_dir(): def compute_project_checksum(config): # rebuild when PIO Core version changes - checksum = sha1(hashlib_encode_data(__version__)) + checksum = sha1(hashlib_encode_data(__version__)) # type: ignore # configuration file state config_data = config.to_json() @@ -104,7 +104,7 @@ def compute_project_checksum(config): config_data, flags=re.I, ) - checksum.update(hashlib_encode_data(config_data)) + checksum.update(hashlib_encode_data(config_data)) # type: ignore # project file structure check_suffixes = (".c", ".cc", ".cpp", ".h", ".hpp", ".s", ".S") @@ -126,7 +126,7 @@ def compute_project_checksum(config): chunks_to_str = ",".join(sorted(chunks)) if IS_WINDOWS: # case insensitive OS chunks_to_str = chunks_to_str.lower() - checksum.update(hashlib_encode_data(chunks_to_str)) + checksum.update(hashlib_encode_data(chunks_to_str)) # type: ignore return checksum.hexdigest() @@ -180,7 +180,7 @@ def _load_build_metadata(project_dir, env_names, build_type=None): if result.exit_code != 0 and not isinstance( result.exception, exception.ReturnErrorCode ): - raise result.exception + raise result.exception # type: ignore if '"includes":' not in result.output: raise exception.UserSideException(result.output) return _get_cached_build_metadata(env_names) diff --git a/platformio/project/options.py b/platformio/project/options.py index d0a4b0e8e9..46d5ca2105 100644 --- a/platformio/project/options.py +++ b/platformio/project/options.py @@ -51,16 +51,16 @@ def __init__( self.validate = validate def as_dict(self): - result = dict( - scope=self.scope, - group=self.group, - name=self.name, - description=self.description, - type="string", - multiple=self.multiple, - sysenvvar=self.sysenvvar, - default=self.default() if callable(self.default) else self.default, - ) + result = { + "scope": self.scope, + "group": self.group, + "name": self.name, + "description": self.description, + "type": "string", + "multiple": self.multiple, + "sysenvvar": self.sysenvvar, + "default": self.default() if callable(self.default) else self.default, + } if isinstance(self.type, click.ParamType): result["type"] = self.type.name if isinstance(self.type, (click.IntRange, click.FloatRange)): diff --git a/platformio/public.py b/platformio/public.py index d3afa020cf..35ff4988ff 100644 --- a/platformio/public.py +++ b/platformio/public.py @@ -27,3 +27,24 @@ from platformio.test.runners.googletest import GoogletestTestRunner from platformio.test.runners.unity import UnityTestRunner from platformio.util import get_systype + + +__all__ = [ + "list_logical_devices", + "list_serial_ports", + "DeviceMonitorFilterBase", + "to_unix_path", + "PlatformBase", + "ProjectConfig", + "get_project_watch_lib_dirs", + "load_build_metadata", + "get_config_options_schema", + "TestCase", + "TestCaseSource", + "TestStatus", + "TestRunnerBase", + "DoctestTestRunner", + "GoogletestTestRunner", + "UnityTestRunner", + "get_systype", +] \ No newline at end of file diff --git a/platformio/registry/client.py b/platformio/registry/client.py index 6ca115c4d8..693c8bd20d 100644 --- a/platformio/registry/client.py +++ b/platformio/registry/client.py @@ -26,17 +26,15 @@ def __init__(self): @staticmethod def allowed_private_packages(): - private_permissions = set( - [ - "service.registry.publish-private-tool", - "service.registry.publish-private-platform", - "service.registry.publish-private-library", - ] - ) + private_permissions = { + "service.registry.publish-private-tool", + "service.registry.publish-private-platform", + "service.registry.publish-private-library", + } try: info = AccountClient().get_account_info() or {} for item in info.get("packages", []): - if set(item.keys()) & private_permissions: + if set(item.keys()) & private_permissions: # type: ignore return True except AccountError: pass @@ -129,9 +127,9 @@ def list_packages(self, query=None, qualifiers=None, page=None, sort=None): search_query.append('%s:"%s"' % (name[:-1], value)) if query: search_query.append(query) - params = dict(query=" ".join(search_query)) + params = {"query": " ".join(search_query)} if page: - params["page"] = int(page) + params["page"] = int(page) # type: ignore if sort: params["sort"] = sort return self.fetch_json_data( @@ -154,7 +152,9 @@ def get_package( name=name.lower(), extra_path=extra_path or "", ), - params=dict(version=version) if version else None, + params={ + "version": version + } if version else None, x_cache_valid="1h", x_with_authorization=self.allowed_private_packages(), ) diff --git a/platformio/registry/mirror.py b/platformio/registry/mirror.py index 8805ffe543..3904d29977 100644 --- a/platformio/registry/mirror.py +++ b/platformio/registry/mirror.py @@ -55,7 +55,7 @@ def __next__(self): self._url_parts.path, allow_redirects=False, params=( - dict(bypass=",".join(self._visited_mirrors)) + {"bypass": ",".join(self._visited_mirrors)} if self._visited_mirrors else None ), diff --git a/platformio/remote/ac/base.py b/platformio/remote/ac/base.py index 0c631c64cc..a340ec0b92 100644 --- a/platformio/remote/ac/base.py +++ b/platformio/remote/ac/base.py @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -from twisted.internet import defer # pylint: disable=import-error -from twisted.spread import pb # pylint: disable=import-error +from twisted.internet import defer # type: ignore +from twisted.spread import pb # type: ignore class AsyncCommandBase: @@ -48,7 +48,7 @@ def start(self): raise NotImplementedError def stop(self): - self.transport.loseConnection() # pylint: disable=no-member + self.transport.loseConnection() # type: ignore def _ac_ended(self): if self.on_end_callback: @@ -82,7 +82,7 @@ def ac_read(self): return None def ac_write(self, data): - self.transport.write(data) # pylint: disable=no-member + self.transport.write(data) # type: ignore return len(data) def ac_close(self): diff --git a/platformio/remote/ac/process.py b/platformio/remote/ac/process.py index 91da456e50..baabdc928c 100644 --- a/platformio/remote/ac/process.py +++ b/platformio/remote/ac/process.py @@ -14,7 +14,7 @@ import os -from twisted.internet import protocol, reactor # pylint: disable=import-error +from twisted.internet import protocol, reactor # type: ignore from platformio.remote.ac.base import AsyncCommandBase @@ -23,7 +23,7 @@ class ProcessAsyncCmd(protocol.ProcessProtocol, AsyncCommandBase): def start(self): env = dict(os.environ).copy() env.update({"PLATFORMIO_FORCE_ANSI": "true"}) - reactor.spawnProcess( + reactor.spawnProcess( # type: ignore self, self.options["executable"], self.options["args"], env ) @@ -34,9 +34,9 @@ def errReceived(self, data): self._ac_ondata(data) def processExited(self, reason): - self._return_code = reason.value.exitCode + self._return_code = reason.value.exitCode # type: ignore def processEnded(self, reason): if self._return_code is None: - self._return_code = reason.value.exitCode + self._return_code = reason.value.exitCode # type: ignore self._ac_ended() diff --git a/platformio/remote/ac/psync.py b/platformio/remote/ac/psync.py index 8728737c07..cf01a8570f 100644 --- a/platformio/remote/ac/psync.py +++ b/platformio/remote/ac/psync.py @@ -44,10 +44,12 @@ def ac_write(self, data): stage = PROJECT_SYNC_STAGE.lookupByValue(data.get("stage")) if stage is PROJECT_SYNC_STAGE.DBINDEX: + assert self.psync is not None self.psync.rebuild_dbindex() return zlib.compress(json.dumps(self.psync.get_dbindex()).encode()) if stage is PROJECT_SYNC_STAGE.DELETE: + assert self.psync is not None return self.psync.delete_dbindex( json.loads(zlib.decompress(data["dbindex"])) ) @@ -57,6 +59,7 @@ def ac_write(self, data): self._upstream = BytesIO() self._upstream.write(data["chunk"]) if self._upstream.tell() == data["total"]: + assert self.psync is not None self.psync.decompress_items(self._upstream) self._upstream = None return PROJECT_SYNC_STAGE.EXTRACTED.value diff --git a/platformio/remote/ac/serial.py b/platformio/remote/ac/serial.py index 7f7f83f951..4874a3939d 100644 --- a/platformio/remote/ac/serial.py +++ b/platformio/remote/ac/serial.py @@ -14,8 +14,8 @@ from time import sleep -from twisted.internet import protocol, reactor # pylint: disable=import-error -from twisted.internet.serialport import SerialPort # pylint: disable=import-error +from twisted.internet import protocol, reactor # type: ignore +from twisted.internet.serialport import SerialPort # type: ignore from platformio.remote.ac.base import AsyncCommandBase @@ -37,17 +37,17 @@ def start(self): def connectionMade(self): self.reset_device() if self.options.get("rts", None) is not None: - self.transport.setRTS(self.options.get("rts")) + self.transport.setRTS(self.options.get("rts")) # type: ignore if self.options.get("dtr", None) is not None: - self.transport.setDTR(self.options.get("dtr")) + self.transport.setDTR(self.options.get("dtr")) # type: ignore def reset_device(self): - self.transport.flushInput() - self.transport.setDTR(False) - self.transport.setRTS(False) + self.transport.flushInput() # type: ignore + self.transport.setDTR(False) # type: ignore + self.transport.setRTS(False) # type: ignore sleep(0.1) - self.transport.setDTR(True) - self.transport.setRTS(True) + self.transport.setDTR(True) # type: ignore + self.transport.setRTS(True) # type: ignore sleep(0.1) def dataReceived(self, data): diff --git a/platformio/remote/cli.py b/platformio/remote/cli.py index 423980f506..bedd9ef116 100644 --- a/platformio/remote/cli.py +++ b/platformio/remote/cli.py @@ -46,8 +46,8 @@ def cli(ctx, agent): # inject twisted dependencies contrib_dir = get_core_package_dir("contrib-pioremote") if contrib_dir not in sys.path: - addsitedir(contrib_dir) - sys.path.insert(0, contrib_dir) + addsitedir(contrib_dir) # type: ignore + sys.path.insert(0, contrib_dir) # type: ignore @cli.group("agent", short_help="Start a new agent or list active") @@ -91,7 +91,7 @@ def remote_agent_list(): def remote_update(agents, only_check, dry_run): from platformio.remote.client.update_core import UpdateCoreClient - UpdateCoreClient("update", agents, dict(only_check=only_check or dry_run)).connect() + UpdateCoreClient("update", agents, {"only_check": only_check or dry_run}).connect() @cli.command("run", short_help="Process project environments remotely") @@ -127,16 +127,16 @@ def remote_run( # pylint: disable=too-many-positional-arguments cr = RunOrTestClient( "run", agents, - dict( - environment=environment, - target=target, - upload_port=upload_port, - project_dir=project_dir, - disable_auto_clean=disable_auto_clean, - force_remote=force_remote, - silent=silent, - verbose=verbose, - ), + { + "environment": environment, + "target": target, + "upload_port": upload_port, + "project_dir": project_dir, + "disable_auto_clean": disable_auto_clean, + "force_remote": force_remote, + "silent": silent, + "verbose": verbose, + }, ) if force_remote: return cr.connect() @@ -145,7 +145,7 @@ def remote_run( # pylint: disable=too-many-positional-arguments local_targets = [] if "clean" in target: local_targets = ["clean"] - elif set(["buildfs", "uploadfs", "uploadfsota"]) & set(target): + elif {"buildfs", "uploadfs", "uploadfsota"} & set(target): local_targets = ["buildfs"] else: local_targets = ["checkprogsize", "buildprog"] @@ -217,18 +217,18 @@ def remote_test( # pylint: disable=redefined-builtin,too-many-positional-argume cr = RunOrTestClient( "test", agents, - dict( - environment=environment, - filter=filter, - ignore=ignore, - upload_port=upload_port, - test_port=test_port, - project_dir=project_dir, - force_remote=force_remote, - without_building=without_building, - without_uploading=without_uploading, - verbose=verbose, - ), + { + "environment": environment, + "filter": filter, + "ignore": ignore, + "upload_port": upload_port, + "test_port": test_port, + "project_dir": project_dir, + "force_remote": force_remote, + "without_building": without_building, + "without_uploading": without_uploading, + "verbose": verbose, + }, ) if force_remote: return cr.connect() diff --git a/platformio/remote/client/agent_list.py b/platformio/remote/client/agent_list.py index 103c0f8cb5..304aa41423 100644 --- a/platformio/remote/client/agent_list.py +++ b/platformio/remote/client/agent_list.py @@ -21,6 +21,7 @@ class AgentListClient(RemoteClientBase): def agent_pool_ready(self): + assert self.agentpool is not None d = self.agentpool.callRemote("list", True) d.addCallback(self._cbResult) d.addErrback(self.cb_global_error) diff --git a/platformio/remote/client/agent_service.py b/platformio/remote/client/agent_service.py index 3a884e6e04..7f90671cbe 100644 --- a/platformio/remote/client/agent_service.py +++ b/platformio/remote/client/agent_service.py @@ -14,8 +14,8 @@ import os -from twisted.logger import LogLevel # pylint: disable=import-error -from twisted.spread import pb # pylint: disable=import-error +from twisted.logger import LogLevel # type: ignore +from twisted.spread import pb # type: ignore from platformio import proc from platformio.device.list.util import list_serial_ports @@ -38,8 +38,8 @@ def __init__(self, name, share, working_dir=None): os.makedirs(self.working_dir) if name: self.name = str(name)[:50] - self.join_options.update( - {"agent": True, "share": [s.lower().strip()[:50] for s in share]} + self.join_options.update( # type: ignore + {"agent": True, "share": [s.lower().strip()[:50] for s in share]} # type: ignore ) self._acs = {} @@ -90,8 +90,8 @@ def _process_cmd_device_list(self, _): def _process_cmd_device_monitor(self, options): if not options["port"]: for item in list_serial_ports(): - if "VID:PID" in item["hwid"]: - options["port"] = item["port"] + if "VID:PID" in item["hwid"]: # type: ignore + options["port"] = item["port"] # type: ignore break # terminate opened monitors diff --git a/platformio/remote/client/async_base.py b/platformio/remote/client/async_base.py index 2a67264132..059a7dfd31 100644 --- a/platformio/remote/client/async_base.py +++ b/platformio/remote/client/async_base.py @@ -13,7 +13,7 @@ # limitations under the License. import click -from twisted.spread import pb # pylint: disable=import-error +from twisted.spread import pb # type: ignore from platformio.remote.client.base import RemoteClientBase @@ -40,7 +40,7 @@ def cb_async_result(self, result): self.acread_data(*value) def acread_data(self, agent_id, ac_id, agent_name=None): - d = self.agentpool.callRemote("acread", agent_id, ac_id) + d = self.agentpool.callRemote("acread", agent_id, ac_id) # type: ignore d.addCallback(self.cb_acread_result, agent_id, ac_id, agent_name) d.addErrback(self.cb_global_error) @@ -54,7 +54,7 @@ def cb_acread_result(self, result, agent_id, ac_id, agent_name): self.acread_data(agent_id, ac_id, agent_name) def acclose(self, agent_id, ac_id): - d = self.agentpool.callRemote("acclose", agent_id, ac_id) + d = self.agentpool.callRemote("acclose", agent_id, ac_id) # type: ignore d.addCallback(self.cb_acclose_result) d.addErrback(self.cb_global_error) diff --git a/platformio/remote/client/base.py b/platformio/remote/client/base.py index cf5c240537..d96790f271 100644 --- a/platformio/remote/client/base.py +++ b/platformio/remote/client/base.py @@ -16,14 +16,14 @@ from time import time import click -from twisted.internet import defer, endpoints, reactor # pylint: disable=import-error -from twisted.logger import ILogObserver # pylint: disable=import-error -from twisted.logger import Logger # pylint: disable=import-error -from twisted.logger import LogLevel # pylint: disable=import-error -from twisted.logger import formatEvent # pylint: disable=import-error -from twisted.python import failure # pylint: disable=import-error -from twisted.spread import pb # pylint: disable=import-error -from zope.interface import provider # pylint: disable=import-error +from twisted.internet import defer, endpoints, reactor # type: ignore +from twisted.logger import ILogObserver # type: ignore +from twisted.logger import Logger # type: ignore +from twisted.logger import LogLevel # type: ignore +from twisted.logger import formatEvent # type: ignore +from twisted.python import failure # type: ignore +from twisted.spread import pb # type: ignore +from zope.interface import provider # type: ignore from platformio import __pioremote_endpoint__, __version__, app, exception, maintenance from platformio.remote.factory.client import RemoteClientFactory @@ -39,7 +39,7 @@ class RemoteClientBase( # pylint: disable=too-many-instance-attributes def __init__(self): self.log_level = LogLevel.warn - self.log = Logger(namespace="remote", observer=self._log_observer) + self.log = Logger(namespace="remote", observer=self._log_observer) # type: ignore self.id = app.get_host_id() self.name = app.get_host_name() self.join_options = {"corever": __version__} @@ -78,21 +78,21 @@ def connect(self): proto = proto[0] factory = RemoteClientFactory() - factory.remote_client = self - factory.sslContextFactory = None + factory.remote_client = self # type: ignore + factory.sslContextFactory = None # type: ignore if proto == "ssl": - factory.sslContextFactory = SSLContextFactory(options["host"]) - reactor.connectSSL( + factory.sslContextFactory = SSLContextFactory(options["host"]) # type: ignore + reactor.connectSSL( # type: ignore options["host"], int(options["port"]), factory, - factory.sslContextFactory, + factory.sslContextFactory, # type: ignore ) elif proto == "tcp": - reactor.connectTCP(options["host"], int(options["port"]), factory) + reactor.connectTCP(options["host"], int(options["port"]), factory) # type: ignore else: raise exception.PlatformioException("Unknown PIO Remote Cloud protocol") - reactor.run() + reactor.run() # type: ignore if self._exit_code != 0: raise exception.ReturnErrorCode(self._exit_code) @@ -130,12 +130,12 @@ def remote_service(self, command, options): def restart_ping(self, reset_counter=True): # stop previous ping callers self.stop_ping(reset_counter) - self._ping_caller = reactor.callLater(self.PING_DELAY, self._do_ping) + self._ping_caller = reactor.callLater(self.PING_DELAY, self._do_ping) # type: ignore def _do_ping(self): self._ping_counter += 1 self._ping_id = int(time()) - d = self.perspective.callRemote("service", "ping", {"id": self._ping_id}) + d = self.perspective.callRemote("service", "ping", {"id": self._ping_id}) # type: ignore d.addCallback(self._cb_pong) d.addErrback(self._cb_pong) @@ -153,7 +153,7 @@ def _cb_pong(self, result): return if self._ping_counter >= self.PING_MAX_FAILURES: self.stop_ping() - self.perspective.broker.transport.loseConnection() + self.perspective.broker.transport.loseConnection() # type: ignore else: self.restart_ping(reset_counter=False) @@ -164,9 +164,9 @@ def disconnect(self, exit_code=None): self.stop_ping() if exit_code is not None: self._exit_code = exit_code - if reactor.running and not self._reactor_stopped: + if reactor.running and not self._reactor_stopped: # type: ignore self._reactor_stopped = True - reactor.stop() + reactor.stop() # type: ignore def cb_disconnected(self, _): self.stop_ping() diff --git a/platformio/remote/client/device_list.py b/platformio/remote/client/device_list.py index f05bbfd27c..32d53841f8 100644 --- a/platformio/remote/client/device_list.py +++ b/platformio/remote/client/device_list.py @@ -26,7 +26,7 @@ def __init__(self, agents, json_output): self.json_output = json_output def agent_pool_ready(self): - d = self.agentpool.callRemote("cmd", self.agents, "device.list") + d = self.agentpool.callRemote("cmd", self.agents, "device.list") # type: ignore d.addCallback(self._cbResult) d.addErrback(self.cb_global_error) diff --git a/platformio/remote/client/device_monitor.py b/platformio/remote/client/device_monitor.py index 4e1ccb2fec..ec54b4d393 100644 --- a/platformio/remote/client/device_monitor.py +++ b/platformio/remote/client/device_monitor.py @@ -16,21 +16,21 @@ from fnmatch import fnmatch import click -from twisted.internet import protocol, reactor, task # pylint: disable=import-error -from twisted.spread import pb # pylint: disable=import-error +from twisted.internet import protocol, reactor, task # type: ignore +from twisted.spread import pb # type: ignore from platformio.remote.client.base import RemoteClientBase class SMBridgeProtocol(protocol.Protocol): def connectionMade(self): - self.factory.add_client(self) + self.factory.add_client(self) # type: ignore def connectionLost(self, reason): # pylint: disable=unused-argument - self.factory.remove_client(self) + self.factory.remove_client(self) # type: ignore def dataReceived(self, data): - self.factory.send_to_server(data) + self.factory.send_to_server(data) # type: ignore class SMBridgeFactory(protocol.ServerFactory): @@ -87,7 +87,7 @@ def __init__(self, agents, **kwargs): def agent_pool_ready(self): d = task.deferLater( - reactor, 1, self.agentpool.callRemote, "cmd", self.agents, "device.list" + reactor, 1, self.agentpool.callRemote, "cmd", self.agents, "device.list" # type: ignore ) d.addCallback(self._cb_device_list) d.addErrback(self.cb_global_error) @@ -106,7 +106,7 @@ def _cb_device_list(self, result): devices.append((agent_name, item)) if len(result) == 1 and self.cmd_options["port"]: - if set(["*", "?", "[", "]"]) & set(self.cmd_options["port"]): + if {"*", "?", "[", "]"} & set(self.cmd_options["port"]): for agent, item in devices: if fnmatch(item["port"], self.cmd_options["port"]): return self.start_remote_monitor(agent, item["port"]) @@ -150,7 +150,7 @@ def start_remote_monitor(self, agent, port): host=agent, port=options["port"] ) ) - d = self.agentpool.callRemote("cmd", [agent], "device.monitor", options) + d = self.agentpool.callRemote("cmd", [agent], "device.monitor", options) # type: ignore d.addCallback(self.cb_async_result) d.addErrback(self.cb_global_error) @@ -170,9 +170,9 @@ def cb_async_result(self, result): return # start bridge - port = reactor.listenTCP(0, self._bridge_factory) - address = port.getHost() - self.log.debug("Serial Bridge is started on {address!r}", address=address) + port = reactor.listenTCP(0, self._bridge_factory) # type: ignore + address = port.getHost() # type: ignore + self.log.debug("Serial Bridge is started on {address!r}", address=address) # type: ignore if "sock" in self.cmd_options: with open( os.path.join(self.cmd_options["sock"], "sock"), @@ -183,7 +183,7 @@ def cb_async_result(self, result): def client_terminal_stopped(self): try: - d = self.agentpool.callRemote("acclose", self._agent_id, self._ac_id) + d = self.agentpool.callRemote("acclose", self._agent_id, self._ac_id) # type: ignore d.addCallback(lambda r: self.disconnect()) d.addErrback(self.cb_global_error) except (AttributeError, pb.DeadReferenceError): @@ -200,7 +200,7 @@ def acread_data(self, force=False): return try: - self._d_acread = self.agentpool.callRemote( + self._d_acread = self.agentpool.callRemote( # type: ignore "acread", self._agent_id, self._ac_id ) self._d_acread.addCallback(self.cb_acread_result) @@ -229,7 +229,7 @@ def acwrite_data(self, data, force=False): data = self._acwrite_buffer self._acwrite_buffer = b"" try: - d = self.agentpool.callRemote("acwrite", self._agent_id, self._ac_id, data) + d = self.agentpool.callRemote("acwrite", self._agent_id, self._ac_id, data) # type: ignore d.addCallback(self.cb_acwrite_result) d.addErrback(self.cb_global_error) except (AttributeError, pb.DeadReferenceError): diff --git a/platformio/remote/client/run_or_test.py b/platformio/remote/client/run_or_test.py index c5fe7da40a..edbc1c116d 100644 --- a/platformio/remote/client/run_or_test.py +++ b/platformio/remote/client/run_or_test.py @@ -18,7 +18,7 @@ import zlib from io import BytesIO -from twisted.spread import pb # pylint: disable=import-error +from twisted.spread import pb # type: ignore from platformio import fs from platformio.compat import hashlib_encode_data @@ -58,7 +58,7 @@ def __init__(self, *args, **kwargs): self.psync = ProjectSync(self.options["project_dir"]) def generate_project_id(self, path): - h = hashlib.sha1(hashlib_encode_data(self.id)) + h = hashlib.sha1(hashlib_encode_data(self.id)) # type: ignore h.update(hashlib_encode_data(path)) return "%s-%s" % (os.path.basename(path), h.hexdigest()) @@ -89,9 +89,7 @@ def _add_project_source_items(self, cfg, psync): psync.add_item( cfg.get("platformio", "src_dir"), "src", cb_filter=self._cb_tarfile_filter ) - if set(["buildfs", "uploadfs", "uploadfsota"]) & set( - self.options.get("target", []) - ): + if {"buildfs", "uploadfs", "uploadfsota"} & set(self.options.get("target", [])): psync.add_item(cfg.get("platformio", "data_dir"), "data") @staticmethod @@ -132,11 +130,11 @@ def agent_pool_ready(self): def psync_init(self): self.add_project_items(self.psync) - d = self.agentpool.callRemote( + d = self.agentpool.callRemote( # type: ignore "cmd", self.agents, "psync", - dict(id=self.project_id, items=[i[1] for i in self.psync.get_items()]), + {"id": self.project_id, "items": [i[1] for i in self.psync.get_items()]}, ) d.addCallback(self.cb_psync_init_result) d.addErrback(self.cb_global_error) @@ -151,11 +149,11 @@ def cb_psync_init_result(self, result): raise pb.Error(value) agent_id, ac_id = value try: - d = self.agentpool.callRemote( + d = self.agentpool.callRemote( # type: ignore "acwrite", agent_id, ac_id, - dict(stage=PROJECT_SYNC_STAGE.DBINDEX.value), + {"stage": PROJECT_SYNC_STAGE.DBINDEX.value}, ) d.addCallback(self.cb_psync_dbindex_result, agent_id, ac_id) d.addErrback(self.cb_global_error) @@ -181,14 +179,14 @@ def cb_psync_dbindex_result(self, result, agent_id, ac_id): return self.psync_upload(agent_id, ac_id, delta) try: - d = self.agentpool.callRemote( + d = self.agentpool.callRemote( # type: ignore "acwrite", agent_id, ac_id, - dict( - stage=PROJECT_SYNC_STAGE.DELETE.value, - dbindex=zlib.compress(json.dumps(delete).encode()), - ), + { + "stage": PROJECT_SYNC_STAGE.DELETE.value, + "dbindex": zlib.compress(json.dumps(delete).encode()), + }, ) d.addCallback(self.cb_psync_delete_result, agent_id, ac_id, delta) d.addErrback(self.cb_global_error) @@ -221,16 +219,16 @@ def psync_upload_chunk(self, agent_id, ac_id, dbindex, fileobj): chunk = fileobj.read(self.UPLOAD_CHUNK_SIZE) assert chunk try: - d = self.agentpool.callRemote( + d = self.agentpool.callRemote( # type: ignore "acwrite", agent_id, ac_id, - dict( - stage=PROJECT_SYNC_STAGE.UPLOAD.value, - chunk=chunk, - length=len(chunk), - total=total, - ), + { + "stage": PROJECT_SYNC_STAGE.UPLOAD.value, + "chunk": chunk, + "length": len(chunk), + "total": total, + }, ) d.addCallback( self.cb_psync_upload_chunk_result, agent_id, ac_id, dbindex, fileobj @@ -255,7 +253,7 @@ def cb_psync_upload_chunk_result( # pylint: disable=too-many-arguments,too-many def psync_finalize(self, agent_id, ac_id): try: - d = self.agentpool.callRemote("acclose", agent_id, ac_id) + d = self.agentpool.callRemote("acclose", agent_id, ac_id) # type: ignore d.addCallback(self.cb_psync_completed_result, agent_id) d.addErrback(self.cb_global_error) except (AttributeError, pb.DeadReferenceError): @@ -266,6 +264,6 @@ def cb_psync_completed_result(self, result, agent_id): options = self.options.copy() del options["project_dir"] options["project_id"] = self.project_id - d = self.agentpool.callRemote("cmd", [agent_id], self.command, options) + d = self.agentpool.callRemote("cmd", [agent_id], self.command, options) # type: ignore d.addCallback(self.cb_async_result) d.addErrback(self.cb_global_error) diff --git a/platformio/remote/client/update_core.py b/platformio/remote/client/update_core.py index 4fdec4cce6..804830e168 100644 --- a/platformio/remote/client/update_core.py +++ b/platformio/remote/client/update_core.py @@ -17,6 +17,6 @@ class UpdateCoreClient(AsyncClientBase): def agent_pool_ready(self): - d = self.agentpool.callRemote("cmd", self.agents, self.command, self.options) + d = self.agentpool.callRemote("cmd", self.agents, self.command, self.options) # type: ignore d.addCallback(self.cb_async_result) d.addErrback(self.cb_global_error) diff --git a/platformio/remote/factory/client.py b/platformio/remote/factory/client.py index b9e3cd5a77..7e85796243 100644 --- a/platformio/remote/factory/client.py +++ b/platformio/remote/factory/client.py @@ -12,9 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from twisted.cred import credentials # pylint: disable=import-error -from twisted.internet import defer, protocol, reactor # pylint: disable=import-error -from twisted.spread import pb # pylint: disable=import-error +from twisted.cred import credentials # type: ignore +from twisted.internet import defer, protocol, reactor # type: ignore +from twisted.spread import pb # type: ignore from platformio.account.client import AccountClient from platformio.app import get_host_id @@ -22,18 +22,18 @@ class RemoteClientFactory(pb.PBClientFactory, protocol.ReconnectingClientFactory): def clientConnectionMade(self, broker): - if self.sslContextFactory and not self.sslContextFactory.certificate_verified: - self.remote_client.log.error( + if self.sslContextFactory and not self.sslContextFactory.certificate_verified: # type: ignore + self.remote_client.log.error( # type: ignore "A remote cloud could not prove that its security certificate is " "from {host}. This may cause a misconfiguration or an attacker " "intercepting your connection.", - host=self.sslContextFactory.host, + host=self.sslContextFactory.host, # type: ignore ) - return self.remote_client.disconnect() + return self.remote_client.disconnect() # type: ignore pb.PBClientFactory.clientConnectionMade(self, broker) protocol.ReconnectingClientFactory.resetDelay(self) - self.remote_client.log.info("Successfully connected") - self.remote_client.log.info("Authenticating") + self.remote_client.log.info("Successfully connected") # type: ignore + self.remote_client.log.info("Authenticating") # type: ignore auth_token = None try: @@ -46,24 +46,24 @@ def clientConnectionMade(self, broker): d = self.login( credentials.UsernamePassword( - auth_token.encode(), + auth_token.encode(), # type: ignore get_host_id().encode(), ), - client=self.remote_client, + client=self.remote_client, # type: ignore ) - d.addCallback(self.remote_client.cb_client_authorization_made) + d.addCallback(self.remote_client.cb_client_authorization_made) # type: ignore d.addErrback(self.clientAuthorizationFailed) return d def clientAuthorizationFailed(self, err): AccountClient.delete_local_session() - self.remote_client.cb_client_authorization_failed(err) + self.remote_client.cb_client_authorization_failed(err) # type: ignore def clientConnectionFailed(self, connector, reason): - self.remote_client.log.warn( + self.remote_client.log.warn( # type: ignore "Could not connect to PIO Remote Cloud. Reconnecting..." ) - self.remote_client.cb_disconnected(reason) + self.remote_client.cb_disconnected(reason) # type: ignore protocol.ReconnectingClientFactory.clientConnectionFailed( self, connector, reason ) @@ -71,16 +71,16 @@ def clientConnectionFailed(self, connector, reason): def clientConnectionLost( # pylint: disable=arguments-differ self, connector, unused_reason ): - if not reactor.running: - self.remote_client.log.info("Successfully disconnected") + if not reactor.running: # type: ignore + self.remote_client.log.info("Successfully disconnected") # type: ignore return - self.remote_client.log.warn( + self.remote_client.log.warn( # type: ignore "Connection is lost to PIO Remote Cloud. Reconnecting" ) pb.PBClientFactory.clientConnectionLost( self, connector, unused_reason, reconnecting=1 ) - self.remote_client.cb_disconnected(unused_reason) + self.remote_client.cb_disconnected(unused_reason) # type: ignore protocol.ReconnectingClientFactory.clientConnectionLost( self, connector, unused_reason ) diff --git a/platformio/remote/factory/ssl.py b/platformio/remote/factory/ssl.py index eeab8bf732..7a550d65d0 100644 --- a/platformio/remote/factory/ssl.py +++ b/platformio/remote/factory/ssl.py @@ -13,8 +13,8 @@ # limitations under the License. import certifi -from OpenSSL import SSL # pylint: disable=import-error -from twisted.internet import ssl # pylint: disable=import-error +from OpenSSL import SSL # type: ignore +from twisted.internet import ssl # type: ignore class SSLContextFactory(ssl.ClientContextFactory): diff --git a/platformio/remote/projectsync.py b/platformio/remote/projectsync.py index 1715145fde..a8b466bebe 100644 --- a/platformio/remote/projectsync.py +++ b/platformio/remote/projectsync.py @@ -17,7 +17,7 @@ from binascii import crc32 from os.path import getmtime, getsize, isdir, isfile, join -from twisted.python import constants # pylint: disable=import-error +import constantly as constants from platformio.compat import hashlib_encode_data @@ -63,7 +63,7 @@ def _insert_to_db(self, path, relpath): if not isfile(path): return index_hash = "%s-%s-%s" % (relpath, getmtime(path), getsize(path)) - index = crc32(hashlib_encode_data(index_hash)) + index = crc32(hashlib_encode_data(index_hash)) # type: ignore self._db[index] = (path, relpath) def get_dbindex(self): @@ -97,7 +97,7 @@ def delete_empty_folders(self): def compress_items(self, fileobj, dbindex, max_size): compressed = [] total_size = 0 - tar_opts = dict(fileobj=fileobj, mode="w:gz", bufsize=0, dereference=True) + tar_opts = {"fileobj": fileobj, "mode": "w:gz", "bufsize": 0, "dereference": True} with tarfile.open(**tar_opts) as tgz: for index in dbindex: compressed.append(index) diff --git a/platformio/run/cli.py b/platformio/run/cli.py index c07db5fde4..10af9cff26 100644 --- a/platformio/run/cli.py +++ b/platformio/run/cli.py @@ -119,7 +119,7 @@ def cli( # pylint: disable=too-many-positional-arguments clean_build_dir(build_dir, config) except ProjectError as exc: raise exc - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except click.secho( "Can not remove temporary directory `%s`. Please remove " "it manually to avoid build issues" % build_dir, @@ -293,7 +293,7 @@ def print_processing_summary(results, verbose=False): click.style(s, bold=True) for s in ("Environment", "Status", "Duration") ], ), - err=failed_nums, + err=failed_nums, # type: ignore ) util.print_labeled_bar( @@ -303,14 +303,14 @@ def print_processing_summary(results, verbose=False): succeeded_nums, util.humanize_duration_time(duration), ), - is_error=failed_nums, + is_error=failed_nums, # type: ignore fg="red" if failed_nums else "green", ) def print_target_list(envs): tabular_data = [] - for env, data in load_build_metadata(os.getcwd(), envs).items(): + for env, data in load_build_metadata(os.getcwd(), envs).items(): # type: ignore tabular_data.extend( sorted( [ diff --git a/platformio/run/processor.py b/platformio/run/processor.py index 7746179467..869264d8b8 100644 --- a/platformio/run/processor.py +++ b/platformio/run/processor.py @@ -46,11 +46,11 @@ def __init__( # pylint: disable=too-many-arguments,too-many-positional-argument self.options = config.items(env=name, as_dict=True) def get_build_variables(self): - variables = dict( - pioenv=self.name, - project_config=self.config.path, - program_args=self.program_args, - ) + variables = { + "pioenv": self.name, + "project_config": self.config.path, + "program_args": self.program_args, + } if CTX_META_TEST_RUNNING_NAME in self.cmd_ctx.meta: variables["piotest_running_name"] = self.cmd_ctx.meta[ diff --git a/platformio/system/commands/info.py b/platformio/system/commands/info.py index 4db1f42895..812c13a19f 100644 --- a/platformio/system/commands/info.py +++ b/platformio/system/commands/info.py @@ -52,7 +52,7 @@ def system_info_cmd(json_output): "value": project_config.get("platformio", "core_dir"), } data["platformio_exe"] = { - "title": "PlatformIO Core Executable", + "title": "PlatformIO Fixed Executable", "value": proc.where_is_program( "platformio.exe" if compat.IS_WINDOWS else "platformio" ), @@ -63,16 +63,16 @@ def system_info_cmd(json_output): } data["global_lib_nums"] = { "title": "Global Libraries", - "value": len(LibraryPackageManager().get_installed()), + "value": len(LibraryPackageManager().get_installed()), # type: ignore } data["dev_platform_nums"] = { "title": "Development Platforms", - "value": len(PlatformPackageManager().get_installed()), + "value": len(PlatformPackageManager().get_installed()), # type: ignore } data["package_tool_nums"] = { "title": "Tools & Toolchains", "value": len( - ToolPackageManager( + ToolPackageManager( # type: ignore project_config.get("platformio", "packages_dir") ).get_installed() ), diff --git a/platformio/system/completion.py b/platformio/system/completion.py index 100d1a1d2b..50c0a47ea7 100644 --- a/platformio/system/completion.py +++ b/platformio/system/completion.py @@ -71,7 +71,7 @@ def is_completion_code_installed(shell, path): def install_completion_code(shell, path): - if shell == ShellType.BASH and get_bash_version() < (4, 4): + if shell == ShellType.BASH and get_bash_version() < (4, 4): # type: ignore raise click.ClickException("The minimal supported Bash version is 4.4") if is_completion_code_installed(shell, path): return None @@ -81,7 +81,7 @@ def install_completion_code(shell, path): fp.write("\n\n# Begin: PlatformIO Core completion support\n") fp.write(get_completion_code(shell)) if append: - fp.write("\n# End: PlatformIO Core completion support\n\n") + fp.write("\n# End: PlatformIO Fixed completion support\n\n") return True diff --git a/platformio/telemetry.py b/platformio/telemetry.py index 5b0734c9a2..c4de1a6284 100644 --- a/platformio/telemetry.py +++ b/platformio/telemetry.py @@ -24,7 +24,7 @@ import requests -from platformio import __title__, __version__, app, exception, fs, util +from platformio import app, exception, fs, util from platformio.cli import PlatformioCLI from platformio.debug.config.base import DebugConfigBase from platformio.http import HTTPSession @@ -143,7 +143,7 @@ def _commit_events(self, events): # skip Bad Request if exc.response.status_code >= 400 and exc.response.status_code < 500: return True - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except pass self._http_offline = True return False @@ -182,7 +182,7 @@ def log_command(ctx): "path_args": PlatformioCLI.reveal_cmd_path_args(ctx), } if is_ci(): - params["ci_actor"] = resolve_ci_actor() or "Unknown" + params["ci_actor"] = resolve_ci_actor() or "Unknown" # type: ignore log_event("cmd_run", params) @@ -289,10 +289,10 @@ def log_debug_exception(exc, debug_config: DebugConfigBase): # cleanup sensitive information, such as paths description = fs.to_unix_path(str(exc)) description = re.sub( - r'(^|\s+|")(?:[a-z]\:)?((/[^"/]+)+)(\s+|"|$)', - lambda m: " %s " % os.path.join(*m.group(2).split("/")[-2:]), - description, - re.I | re.M, + pattern=r'(^|\s+|")(?:[a-z]\:)?((/[^"/]+)+)(\s+|"|$)', + repl=lambda m: " %s " % os.path.join(*m.group(2).split("/")[-2:]), + string=description, + count=re.I | re.M, ) params = { "name": exc.__class__.__name__, @@ -331,7 +331,7 @@ def load_postponed_events(): if not os.path.isfile(state_path): return [] with app.State(state_path) as state: - return state.get("events", []) + return state.get("events", []) # type: ignore def save_postponed_events(events): @@ -340,7 +340,7 @@ def save_postponed_events(events): try: if os.path.isfile(state_path): os.remove(state_path) - except: # pylint: disable=bare-except + except Exception: # pylint: disable=bare-except pass return None with app.State(state_path, lock=True) as state: @@ -369,7 +369,7 @@ def process_postponed_logs(): save_postponed_events([]) # clean telemetry = TelemetryLogger() for event in events: - if set(["name", "params", "timestamp"]) <= set(event.keys()): + if {"name", "params", "timestamp"} <= set(event.keys()): telemetry.log_event( event["name"], event["params"], diff --git a/platformio/test/cli.py b/platformio/test/cli.py index 78a28490b5..fc6ffb2b45 100644 --- a/platformio/test/cli.py +++ b/platformio/test/cli.py @@ -122,7 +122,7 @@ def cli( # pylint: disable=too-many-arguments,too-many-positional-arguments,too test_suites = list_test_suites( project_config, environments=environment, filters=filter, ignores=ignore ) - test_names = sorted(set(s.test_name for s in test_suites)) + test_names = sorted({s.test_name for s in test_suites}) if not verbose: click.echo("Verbosity level can be increased via `-v, -vv, or -vvv` option") @@ -156,7 +156,7 @@ def cli( # pylint: disable=too-many-arguments,too-many-positional-arguments,too print_suite_footer(test_suite) stdout_report = TestReportFactory.new("stdout", test_result) - stdout_report.generate(verbose=verbose or list_tests) + stdout_report.generate(verbose=verbose or list_tests) # type: ignore for output_format, output_path in [ ("json", subprocess.STDOUT if json_output else None), diff --git a/platformio/test/helpers.py b/platformio/test/helpers.py index 25551ef664..07d8ca92e5 100644 --- a/platformio/test/helpers.py +++ b/platformio/test/helpers.py @@ -41,7 +41,7 @@ def list_test_suites(project_config, environments, filters, ignores): for env_name in project_config.envs(): for test_name in test_names: # filter and ignore patterns - patterns = dict(filter=list(filters), ignore=list(ignores)) + patterns = {"filter": list(filters), "ignore": list(ignores)} for key, value in patterns.items(): if value: # overridden from CLI continue diff --git a/platformio/test/reports/json.py b/platformio/test/reports/json.py index 8d834b384c..daa2b6b091 100644 --- a/platformio/test/reports/json.py +++ b/platformio/test/reports/json.py @@ -47,62 +47,62 @@ def generate(self, output_path, verbose=False): return True def to_json(self): - result = dict( - version="1.0", - project_dir=self.test_result.project_dir, - duration=self.test_result.duration, - testcase_nums=self.test_result.case_nums, - error_nums=self.test_result.get_status_nums(TestStatus.ERRORED), - failure_nums=self.test_result.get_status_nums(TestStatus.FAILED), - skipped_nums=self.test_result.get_status_nums(TestStatus.SKIPPED), - test_suites=[], - ) + result = { + "version": "1.0", + "project_dir": self.test_result.project_dir, + "duration": self.test_result.duration, + "testcase_nums": self.test_result.case_nums, + "error_nums": self.test_result.get_status_nums(TestStatus.ERRORED), + "failure_nums": self.test_result.get_status_nums(TestStatus.FAILED), + "skipped_nums": self.test_result.get_status_nums(TestStatus.SKIPPED), + "test_suites": [], + } for test_suite in self.test_result.suites: result["test_suites"].append(self.test_suite_to_json(test_suite)) return result def test_suite_to_json(self, test_suite): - result = dict( - env_name=test_suite.env_name, - test_name=test_suite.test_name, - test_dir=test_suite.test_dir, - status=test_suite.status.name, - duration=test_suite.duration, - timestamp=( + result = { + "env_name": test_suite.env_name, + "test_name": test_suite.test_name, + "test_dir": test_suite.test_dir, + "status": test_suite.status.name, + "duration": test_suite.duration, + "timestamp": ( datetime.datetime.fromtimestamp(test_suite.timestamp).strftime( "%Y-%m-%dT%H:%M:%S" ) if test_suite.timestamp else None ), - testcase_nums=len(test_suite.cases), - error_nums=test_suite.get_status_nums(TestStatus.ERRORED), - failure_nums=test_suite.get_status_nums(TestStatus.FAILED), - skipped_nums=test_suite.get_status_nums(TestStatus.SKIPPED), - test_cases=[], - ) + "testcase_nums": len(test_suite.cases), + "error_nums": test_suite.get_status_nums(TestStatus.ERRORED), + "failure_nums": test_suite.get_status_nums(TestStatus.FAILED), + "skipped_nums": test_suite.get_status_nums(TestStatus.SKIPPED), + "test_cases": [], + } for test_case in test_suite.cases: result["test_cases"].append(self.test_case_to_json(test_case)) return result @staticmethod def test_case_to_json(test_case): - result = dict( - name=test_case.name, - status=test_case.status.name, - message=test_case.message, - stdout=test_case.stdout, - duration=test_case.duration, - exception=None, - source=None, - ) + result = { + "name": test_case.name, + "status": test_case.status.name, + "message": test_case.message, + "stdout": test_case.stdout, + "duration": test_case.duration, + "exception": None, + "source": None, + } if test_case.exception: result["exception"] = "%s: %s" % ( test_case.exception.__class__.__name__, test_case.exception, ) if test_case.source: - result["source"] = dict( - file=test_case.source.filename, line=test_case.source.line - ) + result["source"] = { + "file": test_case.source.filename, "line": test_case.source.line + } return result diff --git a/platformio/test/runners/base.py b/platformio/test/runners/base.py index 308e281e12..b303056ece 100644 --- a/platformio/test/runners/base.py +++ b/platformio/test/runners/base.py @@ -79,7 +79,7 @@ def get_test_speed(self): ) def get_test_port(self): - return self.options.test_port or self.project_config.get( + return self.options.test_port or self.project_config.get( # type: ignore f"env:{self.test_suite.env_name}", "test_port" ) @@ -95,7 +95,7 @@ def start(self, cmd_ctx): self.setup() for stage in ("building", "uploading", "testing"): getattr(self, f"stage_{stage}")() - if self.options.verbose: + if self.options.verbose: # type: ignore click.echo() except Exception as exc: # pylint: disable=broad-except click.secho(str(exc), fg="red", err=True) @@ -114,14 +114,14 @@ def setup(self): pass def stage_building(self): - if self.options.without_building: + if self.options.without_building: # type: ignore return None # run "building" once at the "uploading" stage for the embedded target - if not self.options.without_uploading and self.platform.is_embedded(): + if not self.options.without_uploading and self.platform.is_embedded(): # type: ignore return None click.secho("Building...", bold=True) targets = ["__test"] - if not self.options.without_debugging: + if not self.options.without_debugging: # type: ignore targets.append("__debug") if self.platform.is_embedded(): targets.append("checkprogsize") @@ -135,17 +135,17 @@ def stage_building(self): def stage_uploading(self): is_embedded = self.platform.is_embedded() - if self.options.without_uploading or not is_embedded: + if self.options.without_uploading or not is_embedded: # type: ignore return None click.secho( "Building & Uploading..." if is_embedded else "Uploading...", bold=True ) targets = ["upload"] - if self.options.without_building: + if self.options.without_building: # type: ignore targets.append("nobuild") else: targets.append("__test") - if not self.options.without_debugging: + if not self.options.without_debugging: # type: ignore targets.append("__debug") try: return self.run_project_targets(targets) @@ -156,7 +156,7 @@ def stage_uploading(self): ) from exc def stage_testing(self): - if self.options.without_testing: + if self.options.without_testing: # type: ignore return None click.secho("Testing...", bold=True) test_port = self.get_test_port() @@ -185,9 +185,9 @@ def run_project_targets(self, targets): return self.cmd_ctx.invoke( run_cmd, project_conf=self.project_config.path, - upload_port=self.options.upload_port, - verbose=self.options.verbose > 2, - silent=self.options.verbose < 2, + upload_port=self.options.upload_port, # type: ignore + verbose=self.options.verbose > 2, # type: ignore + silent=self.options.verbose < 2, # type: ignore environment=[self.test_suite.env_name], disable_auto_clean="nobuild" in targets, target=targets, diff --git a/platformio/test/runners/doctest.py b/platformio/test/runners/doctest.py index 30fd6b8c7e..144c740143 100644 --- a/platformio/test/runners/doctest.py +++ b/platformio/test/runners/doctest.py @@ -63,7 +63,7 @@ def _on_divider(self): status=self._tmp_tc.status, message=(self._tmp_tc.message or "").strip() or None, source=self._tmp_tc.source, - stdout=self._tmp_tc.stdout.strip(), + stdout=self._tmp_tc.stdout.strip(), # type: ignore ) self._tmp_tc = TestCase("", TestStatus.PASSED, stdout="") @@ -96,8 +96,8 @@ def _parse_assert(self, line): index = line.find(": %s:" % token) if index == -1: continue - self._tmp_tc.status = status - self._tmp_tc.message = line[index + len(token) + 3 :].strip() or None + self._tmp_tc.status = status # type: ignore + self._tmp_tc.message = line[index + len(token) + 3 :].strip() or None # type: ignore class DoctestTestRunner(TestRunnerBase): @@ -108,13 +108,13 @@ def __init__(self, *args, **kwargs): self._tc_parser = DoctestTestCaseParser() def on_testing_line_output(self, line): - if self.options.verbose: + if self.options.verbose: # type: ignore click.echo(line, nl=False) test_case = self._tc_parser.parse(line) if test_case: self.test_suite.add_case(test_case) - if not self.options.verbose: + if not self.options.verbose: # type: ignore click.echo(test_case.humanize()) if "[doctest] Status:" in line: diff --git a/platformio/test/runners/factory.py b/platformio/test/runners/factory.py index ecb6f88473..fa8e5408e6 100644 --- a/platformio/test/runners/factory.py +++ b/platformio/test/runners/factory.py @@ -42,14 +42,14 @@ def new(cls, test_suite, project_config, options=None) -> TestRunnerBase: runner_cls = None if test_framework == "custom": test_dir = project_config.get("platformio", "test_dir") - custom_runner_path = os.path.join(test_dir, "test_custom_runner.py") + custom_runner_path = os.path.join(test_dir, "test_custom_runner.py") # type: ignore test_name = test_suite.test_name if test_suite.test_name != "*" else None while test_name: - if os.path.isfile( - os.path.join(test_dir, test_name, "test_custom_runner.py") + if os.path.isfile( # type: ignore + os.path.join(test_dir, test_name, "test_custom_runner.py") # type: ignore ): - custom_runner_path = os.path.join( - test_dir, test_name, "test_custom_runner.py" + custom_runner_path = os.path.join( # type: ignore + test_dir, test_name, "test_custom_runner.py" # type: ignore ) break test_name = os.path.dirname(test_name) # parent dir diff --git a/platformio/test/runners/googletest.py b/platformio/test/runners/googletest.py index 80d59c7450..69d0133946 100644 --- a/platformio/test/runners/googletest.py +++ b/platformio/test/runners/googletest.py @@ -55,7 +55,7 @@ def _parse_test_case(self, line): status=TestStatus.from_string(status), message=message, source=source, - stdout=self._tmp_tc.stdout.strip(), + stdout=self._tmp_tc.stdout.strip(), # type: ignore ) self._tmp_tc = None return test_case @@ -96,13 +96,13 @@ def __init__(self, *args, **kwargs): os.environ["GTEST_COLOR"] = "no" # disable ANSI symbols def on_testing_line_output(self, line): - if self.options.verbose: + if self.options.verbose: # type: ignore click.echo(line, nl=False) test_case = self._tc_parser.parse(line) if test_case: self.test_suite.add_case(test_case) - if not self.options.verbose: + if not self.options.verbose: # type: ignore click.echo(test_case.humanize()) if "Global test environment tear-down" in line: diff --git a/platformio/test/runners/readers/native.py b/platformio/test/runners/readers/native.py index 981febc375..9c10137ca7 100644 --- a/platformio/test/runners/readers/native.py +++ b/platformio/test/runners/readers/native.py @@ -18,9 +18,9 @@ import subprocess import time +from platformio.compat import aio_get_running_loop # type: ignore from platformio.compat import ( IS_WINDOWS, - aio_get_running_loop, get_filesystem_encoding, get_locale_encoding, ) diff --git a/platformio/test/runners/readers/serial.py b/platformio/test/runners/readers/serial.py index a9732d7fe6..f218df16de 100644 --- a/platformio/test/runners/readers/serial.py +++ b/platformio/test/runners/readers/serial.py @@ -49,12 +49,12 @@ def begin(self): return if not self.test_runner.options.no_reset: - ser.flushInput() - ser.setDTR(False) - ser.setRTS(False) + ser.flushInput() # type: ignore + ser.setDTR(False) # type: ignore + ser.setRTS(False) # type: ignore sleep(0.1) - ser.setDTR(True) - ser.setRTS(True) + ser.setDTR(True) # type: ignore + ser.setRTS(True) # type: ignore sleep(0.1) while not self.test_runner.test_suite.is_finished(): diff --git a/platformio/test/runners/unity.py b/platformio/test/runners/unity.py index 7b51bf7d15..45feef4c96 100644 --- a/platformio/test/runners/unity.py +++ b/platformio/test/runners/unity.py @@ -110,29 +110,29 @@ class UnityTestRunner(TestRunnerBase): $framework_config_code """ - UNITY_FRAMEWORK_CONFIG = dict( - native=dict( - code=""" + UNITY_FRAMEWORK_CONFIG = { + "native": { + "code": """ #include void unityOutputStart(unsigned long baudrate) { (void) baudrate; } void unityOutputChar(unsigned int c) { putchar(c); } void unityOutputFlush(void) { fflush(stdout); } void unityOutputComplete(void) { } """, - language="c", - ), - arduino=dict( - code=""" + "language": "c", + }, + "arduino": { + "code": """ #include void unityOutputStart(unsigned long baudrate) { Serial.begin(baudrate); } void unityOutputChar(unsigned int c) { Serial.write(c); } void unityOutputFlush(void) { Serial.flush(); } void unityOutputComplete(void) { Serial.end(); } """, - language="cpp", - ), - mbed=dict( - code=""" + "language": "cpp", + }, + "mbed": { + "code": """ #include #if MBED_MAJOR_VERSION == 6 UnbufferedSerial pc(USBTX, USBRX); @@ -150,39 +150,39 @@ class UnityTestRunner(TestRunnerBase): void unityOutputFlush(void) { } void unityOutputComplete(void) { } """, - language="cpp", - ), - espidf=dict( - code=""" + "language": "cpp", + }, + "espidf": { + "code": """ #include void unityOutputStart(unsigned long baudrate) { (void) baudrate; } void unityOutputChar(unsigned int c) { putchar(c); } void unityOutputFlush(void) { fflush(stdout); } void unityOutputComplete(void) { } """, - language="c", - ), - zephyr=dict( - code=""" + "language": "c", + }, + "zephyr": { + "code": """ #include void unityOutputStart(unsigned long baudrate) { (void) baudrate; } void unityOutputChar(unsigned int c) { printk("%c", c); } void unityOutputFlush(void) { } void unityOutputComplete(void) { } """, - language="c", - ), - legacy_custom_transport=dict( - code=""" + "language": "c", + }, + "legacy_custom_transport": { + "code": """ #include void unityOutputStart(unsigned long baudrate) { unittest_uart_begin(); } void unityOutputChar(unsigned int c) { unittest_uart_putchar(c); } void unityOutputFlush(void) { unittest_uart_flush(); } void unityOutputComplete(void) { unittest_uart_end(); } """, - language="cpp", - ), - ) + "language": "cpp", + }, + } def get_unity_framework_config(self): if not self.platform.is_embedded(): @@ -260,7 +260,7 @@ def generate_unity_extras(self, dst_dir): ) def on_testing_line_output(self, line): - if self.options.verbose: + if self.options.verbose: # type: ignore click.echo(line, nl=False) line = strip_ansi_codes(line or "").strip() if not line: @@ -269,7 +269,7 @@ def on_testing_line_output(self, line): test_case = self.parse_test_case(line) if test_case: self.test_suite.add_case(test_case) - if not self.options.verbose: + if not self.options.verbose: # type: ignore click.echo(test_case.humanize()) if all(s in line for s in ("Tests", "Failures", "Ignored")): @@ -288,11 +288,11 @@ def parse_test_case(self, line): source = None if "source_file" in data: source = TestCaseSource( - filename=data["source_file"], line=int(data.get("source_line")) + filename=data["source_file"], line=int(data.get("source_line")) # type: ignore ) return TestCase( - name=data.get("name").strip(), - status=TestStatus.from_string(data.get("status")), + name=data.get("name").strip(), # type: ignore + status=TestStatus.from_string(data.get("status")), # type: ignore message=(data.get("message") or "").strip() or None, stdout=line, source=source, diff --git a/platformio/util.py b/platformio/util.py index e0830a8d68..c598a1dd1f 100644 --- a/platformio/util.py +++ b/platformio/util.py @@ -27,8 +27,6 @@ # pylint: disable=unused-import from platformio.device.list.util import list_serial_ports as get_serial_ports -from platformio.fs import cd, load_json -from platformio.proc import exec_command # pylint: enable=unused-import @@ -57,7 +55,7 @@ def wrapper(*args, **kwargs): self.cache[key] = (time.time(), func(*args, **kwargs)) return self.cache[key][1] - wrapper.reset = self._reset + wrapper.reset = self._reset # type: ignore return wrapper def _reset(self): @@ -212,4 +210,4 @@ def humanize_duration_time(duration): def strip_ansi_codes(text): # pylint: disable=protected-access - return click._compat.strip_ansi(text) + return click._compat.strip_ansi(text) # type: ignore diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..670c649abb --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,108 @@ + +[project] +name = "platformio" +version = "6.2.0" +description = "A professional collaborative platform for embedded development" +readme = "README.rst" +authors = [{ name = "PlatformIO", email = "contact@platformio.org" }] +license = { text = "Apache-2.0" } +requires-python = ">=3.10" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + "Programming Language :: C", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Topic :: Software Development", + "Topic :: Software Development :: Build Tools", + "Topic :: Software Development :: Compilers", +] +keywords = [ + "iot", + "embedded", + "arduino", + "mbed", + "esp8266", + "esp32", + "fpga", + "firmware", + "continuous-integration", + "cloud-ide", + "avr", + "arm", + "ide", + "unit-testing", + "hardware", + "verilog", + "microcontroller", + "debug", +] +dependencies = [ + "bottle == 0.13.*", + "click >=8.0.4, <8.1.8", + "colorama", + "marshmallow == 3.*", + "pyelftools >=0.27, <1", + "pyserial == 3.5.*", + "requests[socks] == 2.*", + "semantic_version == 2.10.*", + "tabulate == 0.*", + "ajsonrpc == 1.2.*", + "starlette >=0.19, <0.47", + "uvicorn >=0.16, <0.35", + "wsproto == 1.*", + 'chardet >= 3.0.2,<6; platform_system == "Darwin" and "arm" in platform_machine', + "urllib3<2", + "twisted>=25.5.0", + "pyopenssl>=25.1.0", + "service-identity>=24.2.0", + "constantly>=23.10.4", +] + +[project.urls] +Homepage = "https://platformio.org" +Documentation = "https://docs.platformio.org" +Repository = "https://github.com/platformio/platformio-core" + +[project.scripts] +platformio = "platformio.__main__:main" +pio = "platformio.__main__:main" +piodebuggdb = "platformio.__main__:debug_gdb_main" + +[project.optional-dependencies] +dev = [ + "ruff", + "isort", + "pyright", + "pytest", + "pytest-xdist", + "codespell", + "jsondiff", +] + +[tool.ruff.lint] +select = ["E", "W", "F", "I", "C", "B"] +ignore = ["E501", "C901", "F401", "C414"] + +[tool.ruff] +line-length = 88 + +[tool.isort] +profile = "black" +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +use_parentheses = true +ensure_newline_before_comments = true +line_length = 88 + +[tool.pyright] +include = ["platformio", "tests"] +exclude = ["**/node_modules", "**/__pycache__"] +typeCheckingMode = "basic" +pythonVersion = "3.6" +reportMissingImports = true +reportMissingTypeStubs = false diff --git a/scripts/docspregen.py b/scripts/docspregen.py index 38b4c52cfc..c30b5e8211 100644 --- a/scripts/docspregen.py +++ b/scripts/docspregen.py @@ -26,7 +26,6 @@ from platformio.package.manager.platform import PlatformPackageManager # noqa: E402 from platformio.platform.factory import PlatformFactory # noqa: E402 - RST_COPYRIGHT = """.. Copyright (c) 2014-present PlatformIO Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -98,7 +97,7 @@ def install_platforms(): page = 1 pm = PlatformPackageManager() while True: - result = REGCLIENT.list_packages(qualifiers=dict(types=["platform"]), page=page) + result = REGCLIENT.list_packages(qualifiers={"types": ["platform"]}, page=page) for item in result["items"]: spec = "%s/%s" % (item["owner"]["username"], item["name"]) skip_conds = [ @@ -123,11 +122,11 @@ def get_frameworks(): if name in items: continue if name in STATIC_FRAMEWORK_DATA: - items[name] = dict( - name=name, - title=STATIC_FRAMEWORK_DATA[name]["title"], - description=STATIC_FRAMEWORK_DATA[name]["description"], - ) + items[name] = { + "name": name, + "title": STATIC_FRAMEWORK_DATA[name]["title"], + "description": STATIC_FRAMEWORK_DATA[name]["description"], + } continue title = options.get("title") or name.title() description = options.get("description") @@ -139,7 +138,7 @@ def get_frameworks(): ) title = regdata["title"] or title description = regdata["description"] - items[name] = dict(name=name, title=title, description=description) + items[name] = {"name": name, "title": title, "description": description} return sorted(items.values(), key=lambda item: item["name"]) @@ -167,7 +166,7 @@ def generate_boards_table(boards, skip_columns=None): ) # add header - for name, template in columns: + for name, _template in columns: if skip_columns and name in skip_columns: continue prefix = " * - " if name == "Name" else " - " @@ -183,22 +182,22 @@ def generate_boards_table(boards, skip_columns=None): elif data.get("debug"): debug = "External" - variables = dict( - id=data["id"], - name=data["name"], - platform=data["platform"], - debug=debug, - mcu=data["mcu"].upper(), - f_cpu=int(data["fcpu"] / 1000000.0), - ram=fs.humanize_file_size(data["ram"]), - rom=fs.humanize_file_size(data["rom"]), - ) - - for name, template in columns: + variables = { + "id": data["id"], + "name": data["name"], + "platform": data["platform"], + "debug": debug, + "mcu": data["mcu"].upper(), + "f_cpu": int(data["fcpu"] / 1000000.0), + "ram": fs.humanize_file_size(data["ram"]), + "rom": fs.humanize_file_size(data["rom"]), + } + + for name, _template in columns: if skip_columns and name in skip_columns: continue prefix = " * - " if name == "Name" else " - " - lines.append(prefix + template.format(**variables)) + lines.append(prefix + _template.format(**variables)) if lines: lines.append("") @@ -774,22 +773,22 @@ def update_embedded_board(rst_path, board): board_manifest_url = board_manifest_url[:-4] board_manifest_url += "/blob/master/boards/%s.json" % board["id"] - variables = dict( - id=board["id"], - name=board["name"], - platform=board["platform"], - platform_description=platform.description, - url=campaign_url(board["url"]), - mcu=board_config.get("build", {}).get("mcu", ""), - mcu_upper=board["mcu"].upper(), - f_cpu=board["fcpu"], - f_cpu_mhz=int(int(board["fcpu"]) / 1000000), - ram=fs.humanize_file_size(board["ram"]), - rom=fs.humanize_file_size(board["rom"]), - vendor=board["vendor"], - board_manifest_url=board_manifest_url, - upload_protocol=board_config.get("upload.protocol", ""), - ) + variables = { + "id": board["id"], + "name": board["name"], + "platform": board["platform"], + "platform_description": platform.description, + "url": campaign_url(board["url"]), + "mcu": board_config.get("build", {}).get("mcu", ""), + "mcu_upper": board["mcu"].upper(), + "f_cpu": board["fcpu"], + "f_cpu_mhz": int(int(board["fcpu"]) / 1000000), + "ram": fs.humanize_file_size(board["ram"]), + "rom": fs.humanize_file_size(board["rom"]), + "vendor": board["vendor"], + "board_manifest_url": board_manifest_url, + "upload_protocol": board_config.get("upload.protocol", ""), + } lines = [RST_COPYRIGHT] lines.append(".. _board_{platform}_{id}:".format(**variables)) diff --git a/scripts/fixsymlink.py b/scripts/fixsymlink.py index 0f9daa2e7c..d8e5c34633 100644 --- a/scripts/fixsymlink.py +++ b/scripts/fixsymlink.py @@ -28,7 +28,7 @@ def fix_symlink(root, fname, brokenlink): def main(): - for root, dirnames, filenames in walk("."): + for root, _dirnames, filenames in walk("."): for f in filenames: path = join(root, f) if not islink(path) or exists(path): diff --git a/setup.py b/setup.py index e4eae2386d..57beab7872 100644 --- a/setup.py +++ b/setup.py @@ -49,8 +49,8 @@ }, entry_points={ "console_scripts": [ - "platformio = platformio.__main__:main", - "pio = platformio.__main__:main", + "platformio-fixed = platformio.__main__:main", + "pio-fixed = platformio.__main__:main", "piodebuggdb = platformio.__main__:debug_gdb_main", ] }, diff --git a/test b/test new file mode 100644 index 0000000000..d69cb120d3 --- /dev/null +++ b/test @@ -0,0 +1,6 @@ + +#!/bin/bash + +# This script runs the linters on the project. + +uv run pytest -v -k "not skip_ci" tests --ignore tests/test_examples.py --durations=0 \ No newline at end of file diff --git a/tests/commands/pkg/test_exec.py b/tests/commands/pkg/test_exec.py index 0b0c0f4430..4dc512c99a 100644 --- a/tests/commands/pkg/test_exec.py +++ b/tests/commands/pkg/test_exec.py @@ -37,7 +37,7 @@ def test_pkg_specified(clirunner, validate_cliresult, isolated_pio_core): result = clirunner.invoke( package_exec_cmd, ["-p", "platformio/tool-openocd", "--", "openocd", "--version"], - obj=dict(force_click_stream=True), + obj={"force_click_stream": True}, ) validate_cliresult(result) output = strip_ansi_codes(result.output) @@ -50,10 +50,15 @@ def test_unrecognized_options(clirunner, validate_cliresult, isolated_pio_core): result = clirunner.invoke( package_exec_cmd, ["--", "openocd", "--test-unrecognized"], - obj=dict(force_click_stream=True), + obj={"force_click_stream": True}, ) with pytest.raises( AssertionError, match=(r"openocd: (unrecognized|unknown) option"), ): validate_cliresult(result) + + +if __name__ == "__main__": + import pytest + pytest.main() \ No newline at end of file diff --git a/tests/commands/test_boards.py b/tests/commands/test_boards.py index 244f0b7038..00e450bc95 100644 --- a/tests/commands/test_boards.py +++ b/tests/commands/test_boards.py @@ -33,7 +33,7 @@ def test_board_raw_output(clirunner, validate_cliresult): def test_board_options(clirunner, validate_cliresult): - required_opts = set(["fcpu", "frameworks", "id", "mcu", "name", "platform"]) + required_opts = {"fcpu", "frameworks", "id", "mcu", "name", "platform"} # fetch available platforms result = clirunner.invoke(cmd_platform_search, ["--json-output"]) diff --git a/tests/commands/test_check.py b/tests/commands/test_check.py index 5f32e77d71..fc43162eab 100644 --- a/tests/commands/test_check.py +++ b/tests/commands/test_check.py @@ -439,7 +439,7 @@ def test_check_fails_on_defects_only_on_specified_level( assert low_result.exit_code != 0 - +@pytest.mark.skip(reason="Test takes too long to run") def test_check_pvs_studio_free_license(clirunner, tmpdir): config = """ [env:test] @@ -512,6 +512,7 @@ def test_check_pvs_studio_fails_broken_license(clirunner, tmpdir): assert "license information is incorrect" in verbose_result.output.lower() +# @pytest.mark.skip(reason="Test takes too long to run") @pytest.mark.parametrize("framework", ["arduino", "stm32cube", "zephyr"]) @pytest.mark.parametrize("check_tool", ["cppcheck", "clangtidy", "pvs-studio"]) def test_check_embedded_platform_all_tools( diff --git a/tests/commands/test_ci.py b/tests/commands/test_ci.py index f67bada4d9..0e442a3a07 100644 --- a/tests/commands/test_ci.py +++ b/tests/commands/test_ci.py @@ -191,3 +191,8 @@ def test_ci_lib_and_board(clirunner, tmpdir_factory, validate_cliresult): ], ) validate_cliresult(result) + + +if __name__ == "__main__": + import pytest + pytest.main() \ No newline at end of file diff --git a/tests/commands/test_init.py b/tests/commands/test_init.py index a8bffc5d6e..c175a35691 100644 --- a/tests/commands/test_init.py +++ b/tests/commands/test_init.py @@ -58,7 +58,7 @@ def test_init_duplicated_boards(clirunner, validate_cliresult, tmpdir): validate_pioproject(project_dir) config = ProjectConfig(os.path.join(project_dir, "platformio.ini")) config.validate() - assert set(config.sections()) == set(["env:uno"]) + assert set(config.sections()) == {"env:uno"} def test_init_ide_without_board(clirunner, tmpdir): @@ -153,11 +153,11 @@ def test_init_special_board(clirunner, validate_cliresult): config = ProjectConfig(os.path.join(os.getcwd(), "platformio.ini")) config.validate() - expected_result = dict( - platform=str(boards[0]["platform"]), - board="uno", - framework=[str(boards[0]["frameworks"][0])], - ) + expected_result = { + "platform": str(boards[0]["platform"]), + "board": "uno", + "framework": [str(boards[0]["frameworks"][0])], + } assert config.has_section("env:uno") assert sorted(config.items(env="uno", as_dict=True).items()) == sorted( expected_result.items() @@ -180,9 +180,9 @@ def test_init_enable_auto_uploading(clirunner, validate_cliresult): validate_pioproject(os.getcwd()) config = ProjectConfig(os.path.join(os.getcwd(), "platformio.ini")) config.validate() - expected_result = dict( - targets=["upload"], platform="atmelavr", board="uno", framework=["arduino"] - ) + expected_result = { + "targets": ["upload"], "platform": "atmelavr", "board": "uno", "framework": ["arduino"] + } assert config.has_section("env:uno") assert sorted(config.items(env="uno", as_dict=True).items()) == sorted( expected_result.items() @@ -205,7 +205,7 @@ def test_init_custom_framework(clirunner, validate_cliresult): validate_pioproject(os.getcwd()) config = ProjectConfig(os.path.join(os.getcwd(), "platformio.ini")) config.validate() - expected_result = dict(platform="teensy", board="teensy31", framework=["mbed"]) + expected_result = {"platform": "teensy", "board": "teensy31", "framework": ["mbed"]} assert config.has_section("env:teensy31") assert sorted(config.items(env="teensy31", as_dict=True).items()) == sorted( expected_result.items() diff --git a/tests/commands/test_lib_complex.py b/tests/commands/test_lib_complex.py index f14d9d4c27..2dbd32cb83 100644 --- a/tests/commands/test_lib_complex.py +++ b/tests/commands/test_lib_complex.py @@ -234,9 +234,7 @@ def test_global_lib_update_check(clirunner, validate_cliresult): result = clirunner.invoke(cmd_lib, ["-g", "update", "--dry-run", "--json-output"]) validate_cliresult(result) output = json.loads(result.output) - assert set( - ["Adafruit PN532", "AsyncMqttClient", "AsyncTCP", "ESPAsyncTCP", "NeoPixelBus"] - ) == set(lib["name"] for lib in output) + assert {"Adafruit PN532", "AsyncMqttClient", "AsyncTCP", "ESPAsyncTCP", "NeoPixelBus"} == {lib["name"] for lib in output} def test_global_lib_update(clirunner, validate_cliresult): @@ -332,14 +330,12 @@ def test_lib_builtin(clirunner, validate_cliresult): def test_lib_stats(clirunner, validate_cliresult): result = clirunner.invoke(cmd_lib, ["stats", "--json-output"]) validate_cliresult(result) - assert set( - [ - "dlweek", - "added", - "updated", - "topkeywords", - "dlmonth", - "dlday", - "lastkeywords", - ] - ) == set(json.loads(result.output).keys()) + assert { + "dlweek", + "added", + "updated", + "topkeywords", + "dlmonth", + "dlday", + "lastkeywords", + } == set(json.loads(result.output).keys()) diff --git a/tests/commands/test_platform.py b/tests/commands/test_platform.py index b832a366f4..3656cb7fc6 100644 --- a/tests/commands/test_platform.py +++ b/tests/commands/test_platform.py @@ -99,7 +99,7 @@ def test_list_json_output(clirunner, validate_cliresult): assert isinstance(list_result, list) assert list_result platforms = [item["name"] for item in list_result] - assert set(["atmelavr", "espressif8266"]) == set(platforms) + assert {"atmelavr", "espressif8266"} == set(platforms) def test_list_raw_output(clirunner, validate_cliresult): diff --git a/tests/misc/ino2cpp/test_ino2cpp.py b/tests/misc/ino2cpp/test_ino2cpp.py index 72e3bcdd8c..b7501ce41f 100644 --- a/tests/misc/ino2cpp/test_ino2cpp.py +++ b/tests/misc/ino2cpp/test_ino2cpp.py @@ -46,3 +46,8 @@ def test_warning_line(clirunner, validate_cliresult): ) validate_cliresult(result) assert 'main.ino:75:2: warning: #warning "Line 75"' in result.output + + +if __name__ == "__main__": + import pytest + pytest.main() \ No newline at end of file diff --git a/tests/package/test_manager.py b/tests/package/test_manager.py index 977cde9dc0..e976ad720e 100644 --- a/tests/package/test_manager.py +++ b/tests/package/test_manager.py @@ -269,9 +269,7 @@ def test_install_lib_depndencies(isolated_pio_core, tmpdir_factory): lm.install("file://%s" % str(src_dir)) installed = lm.get_installed() assert len(installed) == 4 - assert set(["external-repo", "ArduinoJson", "lib-with-deps", "OneWire"]) == set( - p.metadata.name for p in installed - ) + assert {"external-repo", "ArduinoJson", "lib-with-deps", "OneWire"} == {p.metadata.name for p in installed} def test_install_force(isolated_pio_core, tmpdir_factory): @@ -511,9 +509,7 @@ def test_get_installed(isolated_pio_core, tmpdir_factory): installed = pm.get_installed() assert len(installed) == 4 - assert set(["pkg-via-vcs", "foo", "check-system"]) == set( - p.metadata.name for p in installed - ) + assert {"pkg-via-vcs", "foo", "check-system"} == {p.metadata.name for p in installed} assert str(pm.get_package("foo").metadata.version) == "3.6.0" assert str(pm.get_package("check-system").metadata.version) == "3.0.0" diff --git a/tests/package/test_manifest.py b/tests/package/test_manifest.py index bcc7e00a6f..5058fdaa43 100644 --- a/tests/package/test_manifest.py +++ b/tests/package/test_manifest.py @@ -864,16 +864,14 @@ def test_broken_schemas(): with pytest.raises( ManifestValidationError, match=("Invalid semantic versioning format") ) as exc_info: - ManifestSchema().load_manifest(dict(name="MyPackage", version="broken_version")) + ManifestSchema().load_manifest({"name": "MyPackage", "version": "broken_version"}) assert exc_info.value.valid_data == {"name": "MyPackage"} # invalid StrictList with pytest.raises( ManifestValidationError, match=("Invalid manifest fields.+keywords") ) as exc_info: - ManifestSchema().load_manifest( - dict(name="MyPackage", version="1.0.0", keywords=["kw1", "*^[]"]) - ) + ManifestSchema().load_manifest({"name": "MyPackage", "version": "1.0.0", "keywords": ["kw1", "*^[]"]}) assert list(exc_info.value.messages.keys()) == ["keywords"] assert exc_info.value.valid_data["keywords"] == ["kw1"] @@ -881,25 +879,23 @@ def test_broken_schemas(): with pytest.raises( ManifestValidationError, match=("Invalid semantic versioning format") ): - ManifestSchema().load_manifest(dict(name="MyPackage", version="broken_version")) + ManifestSchema().load_manifest({"name": "MyPackage", "version": "broken_version"}) # version with leading zeros with pytest.raises( ManifestValidationError, match=("Invalid semantic versioning format") ): - ManifestSchema().load_manifest(dict(name="MyPackage", version="01.02.00")) + ManifestSchema().load_manifest({"name": "MyPackage", "version": "01.02.00"}) # broken value for Nested with pytest.raises(ManifestValidationError, match=r"authors.*Invalid input type"): - ManifestSchema().load_manifest( - dict( - name="MyPackage", - description="MyDescription", - keywords=["a", "b"], - authors=["should be dict here"], - version="1.2.3", - ) - ) + ManifestSchema().load_manifest({ + "name": "MyPackage", + "description": "MyDescription", + "keywords": ["a", "b"], + "authors": ["should be dict here"], + "version": "1.2.3", + }) # invalid package name with pytest.raises(ManifestValidationError, match="are not allowed"): - ManifestSchema().load_manifest(dict(name="C/C++ :library", version="1.2.3")) + ManifestSchema().load_manifest({"name": "C/C++ :library", "version": "1.2.3"}) diff --git a/tests/package/test_pack.py b/tests/package/test_pack.py index 558591b318..55db4b5c6f 100644 --- a/tests/package/test_pack.py +++ b/tests/package/test_pack.py @@ -40,9 +40,7 @@ def test_base(tmpdir_factory): with fs.cd(str(pkg_dir)): p.pack() with tarfile.open(os.path.join(str(pkg_dir), "foo-1.0.0.tar.gz"), "r:gz") as tar: - assert set(tar.getnames()) == set( - [".gitignore", "include/main.h", "library.json", "main.cpp"] - ) + assert set(tar.getnames()) == {".gitignore", "include/main.h", "library.json", "main.cpp"} def test_filters(tmpdir_factory): @@ -57,42 +55,32 @@ def test_filters(tmpdir_factory): # test include with remap of root pkg_dir.join("library.json").write( - json.dumps(dict(name="bar", version="1.2.3", export={"include": "src"})) + json.dumps({"name": "bar", "version": "1.2.3", "export": {"include": "src"}}) ) p = PackagePacker(str(pkg_dir)) with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar: - assert set(tar.getnames()) == set( - ["util/helpers.cpp", "main.cpp", "library.json"] - ) + assert set(tar.getnames()) == {"util/helpers.cpp", "main.cpp", "library.json"} os.unlink(str(src_dir.join("library.json"))) # test include "src" and "include" pkg_dir.join("library.json").write( - json.dumps( - dict(name="bar", version="1.2.3", export={"include": ["src", "include"]}) - ) + json.dumps({"name": "bar", "version": "1.2.3", "export": {"include": ["src", "include"]}}) ) p = PackagePacker(str(pkg_dir)) with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar: - assert set(tar.getnames()) == set( - ["include/main.h", "library.json", "src/main.cpp", "src/util/helpers.cpp"] - ) + assert set(tar.getnames()) == {"include/main.h", "library.json", "src/main.cpp", "src/util/helpers.cpp"} # test include & exclude pkg_dir.join("library.json").write( - json.dumps( - dict( - name="bar", - version="1.2.3", - export={"include": ["src", "include"], "exclude": ["*/*.h"]}, - ) - ) + json.dumps({ + "name": "bar", + "version": "1.2.3", + "export": {"include": ["src", "include"], "exclude": ["*/*.h"]}, + }) ) p = PackagePacker(str(pkg_dir)) with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar: - assert set(tar.getnames()) == set( - ["library.json", "src/main.cpp", "src/util/helpers.cpp"] - ) + assert set(tar.getnames()) == {"library.json", "src/main.cpp", "src/util/helpers.cpp"} def test_gitgnore_filters(tmpdir_factory): @@ -126,9 +114,7 @@ def test_gitgnore_filters(tmpdir_factory): with fs.cd(str(pkg_dir)): p.pack() with tarfile.open(os.path.join(str(pkg_dir), "foo-1.0.0.tar.gz"), "r:gz") as tar: - assert set(tar.getnames()) == set( - ["library.json", "LICENSE", ".gitignore", "gi_keep_file"] - ) + assert set(tar.getnames()) == {"library.json", "LICENSE", ".gitignore", "gi_keep_file"} def test_symlinks(tmpdir_factory): @@ -149,9 +135,7 @@ def test_symlinks(tmpdir_factory): p = PackagePacker(str(tarball)) assert p.pack(str(pkg_dir)).endswith("bar-2.0.0.tar.gz") with tarfile.open(os.path.join(str(pkg_dir), "bar-2.0.0.tar.gz"), "r:gz") as tar: - assert set(tar.getnames()) == set( - ["include/main.h", "library.json", "src/main.cpp", "src/main.h"] - ) + assert set(tar.getnames()) == {"include/main.h", "library.json", "src/main.cpp", "src/main.h"} m = tar.getmember("src/main.h") assert m.issym() @@ -164,7 +148,7 @@ def test_source_root(tmpdir_factory): root_dir.join("library.json").write('{"name": "bar", "version": "2.0.0"}') p = PackagePacker(str(pkg_dir)) with tarfile.open(p.pack(str(pkg_dir)), "r:gz") as tar: - assert set(tar.getnames()) == set(["library.json", "src/main.cpp"]) + assert set(tar.getnames()) == {"library.json", "src/main.cpp"} def test_manifest_uri(tmpdir_factory): @@ -185,4 +169,4 @@ def test_manifest_uri(tmpdir_factory): p = PackagePacker(str(pkg_dir), manifest_uri="file:%s" % manifest_path) p.pack(str(pkg_dir)) with tarfile.open(os.path.join(str(pkg_dir), "bar-2.0.0.tar.gz"), "r:gz") as tar: - assert set(tar.getnames()) == set(["library.json", "include/bar.h"]) + assert set(tar.getnames()) == {"library.json", "include/bar.h"} diff --git a/tox.ini b/tox.ini index 0be8ec1e71..1324c95814 100644 --- a/tox.ini +++ b/tox.ini @@ -35,7 +35,7 @@ deps = pytest-xdist commands = {envpython} --version - pio system info + pio-fixed system info [testenv:lint] commands = diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000000..9f4a12d0e1 --- /dev/null +++ b/uv.lock @@ -0,0 +1,888 @@ +version = 1 +revision = 2 +requires-python = ">=3.10" + +[[package]] +name = "ajsonrpc" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/5c/95a9b83195d37620028421e00d69d598aafaa181d3e55caec485468838e1/ajsonrpc-1.2.0.tar.gz", hash = "sha256:791bac18f0bf0dee109194644f151cf8b7ff529c4b8d6239ac48104a3251a19f", size = 22108, upload-time = "2021-07-21T20:41:47.376Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/6f/6abff7fe6813e6f94129a50c8c70bf70fb33ed2515b1037e703cef6d7a7e/ajsonrpc-1.2.0-py3-none-any.whl", hash = "sha256:0fa2c1cf8e619d18ffee96043822032d6520eda65d3b712f9540a3a63e9cac25", size = 22753, upload-time = "2021-07-21T20:41:46.245Z" }, +] + +[[package]] +name = "anyio" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "sniffio" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/7d/4c1bd541d4dffa1b52bd83fb8527089e097a106fc90b467a7313b105f840/anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", size = 190949, upload-time = "2025-03-17T00:02:54.77Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/ee/48ca1a7c89ffec8b6a0c5d02b89c305671d5ffd8d3c94acf8b8c408575bb/anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c", size = 100916, upload-time = "2025-03-17T00:02:52.713Z" }, +] + +[[package]] +name = "attrs" +version = "25.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/1367933a8532ee6ff8d63537de4f1177af4bff9f3e829baf7331f595bb24/attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b", size = 812032, upload-time = "2025-03-13T11:10:22.779Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", size = 63815, upload-time = "2025-03-13T11:10:21.14Z" }, +] + +[[package]] +name = "automat" +version = "25.4.16" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e3/0f/d40bbe294bbf004d436a8bcbcfaadca8b5140d39ad0ad3d73d1a8ba15f14/automat-25.4.16.tar.gz", hash = "sha256:0017591a5477066e90d26b0e696ddc143baafd87b588cfac8100bc6be9634de0", size = 129977, upload-time = "2025-04-16T20:12:16.002Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/ff/1175b0b7371e46244032d43a56862d0af455823b5280a50c63d99cc50f18/automat-25.4.16-py3-none-any.whl", hash = "sha256:04e9bce696a8d5671ee698005af6e5a9fa15354140a87f4870744604dcdd3ba1", size = 42842, upload-time = "2025-04-16T20:12:14.447Z" }, +] + +[[package]] +name = "bottle" +version = "0.13.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7a/71/cca6167c06d00c81375fd668719df245864076d284f7cb46a694cbeb5454/bottle-0.13.4.tar.gz", hash = "sha256:787e78327e12b227938de02248333d788cfe45987edca735f8f88e03472c3f47", size = 98717, upload-time = "2025-06-15T10:08:59.439Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/f6/b55ec74cfe68c6584163faa311503c20b0da4c09883a41e8e00d6726c954/bottle-0.13.4-py2.py3-none-any.whl", hash = "sha256:045684fbd2764eac9cdeb824861d1551d113e8b683d8d26e296898d3dd99a12e", size = 103807, upload-time = "2025-06-15T10:08:57.691Z" }, +] + +[[package]] +name = "certifi" +version = "2025.6.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, +] + +[[package]] +name = "cffi" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191, upload-time = "2024-09-04T20:43:30.027Z" }, + { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592, upload-time = "2024-09-04T20:43:32.108Z" }, + { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024, upload-time = "2024-09-04T20:43:34.186Z" }, + { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188, upload-time = "2024-09-04T20:43:36.286Z" }, + { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571, upload-time = "2024-09-04T20:43:38.586Z" }, + { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687, upload-time = "2024-09-04T20:43:40.084Z" }, + { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211, upload-time = "2024-09-04T20:43:41.526Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325, upload-time = "2024-09-04T20:43:43.117Z" }, + { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784, upload-time = "2024-09-04T20:43:45.256Z" }, + { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564, upload-time = "2024-09-04T20:43:46.779Z" }, + { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804, upload-time = "2024-09-04T20:43:48.186Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299, upload-time = "2024-09-04T20:43:49.812Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264, upload-time = "2024-09-04T20:43:51.124Z" }, + { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651, upload-time = "2024-09-04T20:43:52.872Z" }, + { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259, upload-time = "2024-09-04T20:43:56.123Z" }, + { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200, upload-time = "2024-09-04T20:43:57.891Z" }, + { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235, upload-time = "2024-09-04T20:44:00.18Z" }, + { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721, upload-time = "2024-09-04T20:44:01.585Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242, upload-time = "2024-09-04T20:44:03.467Z" }, + { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999, upload-time = "2024-09-04T20:44:05.023Z" }, + { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242, upload-time = "2024-09-04T20:44:06.444Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604, upload-time = "2024-09-04T20:44:08.206Z" }, + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727, upload-time = "2024-09-04T20:44:09.481Z" }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400, upload-time = "2024-09-04T20:44:10.873Z" }, + { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" }, + { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" }, +] + +[[package]] +name = "chardet" +version = "5.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618, upload-time = "2023-08-01T19:23:02.662Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385, upload-time = "2023-08-01T19:23:00.661Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/28/9901804da60055b406e1a1c5ba7aac1276fb77f1dde635aabfc7fd84b8ab/charset_normalizer-3.4.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", size = 201818, upload-time = "2025-05-02T08:31:46.725Z" }, + { url = "https://files.pythonhosted.org/packages/d9/9b/892a8c8af9110935e5adcbb06d9c6fe741b6bb02608c6513983048ba1a18/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", size = 144649, upload-time = "2025-05-02T08:31:48.889Z" }, + { url = "https://files.pythonhosted.org/packages/7b/a5/4179abd063ff6414223575e008593861d62abfc22455b5d1a44995b7c101/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", size = 155045, upload-time = "2025-05-02T08:31:50.757Z" }, + { url = "https://files.pythonhosted.org/packages/3b/95/bc08c7dfeddd26b4be8c8287b9bb055716f31077c8b0ea1cd09553794665/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", size = 147356, upload-time = "2025-05-02T08:31:52.634Z" }, + { url = "https://files.pythonhosted.org/packages/a8/2d/7a5b635aa65284bf3eab7653e8b4151ab420ecbae918d3e359d1947b4d61/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", size = 149471, upload-time = "2025-05-02T08:31:56.207Z" }, + { url = "https://files.pythonhosted.org/packages/ae/38/51fc6ac74251fd331a8cfdb7ec57beba8c23fd5493f1050f71c87ef77ed0/charset_normalizer-3.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", size = 151317, upload-time = "2025-05-02T08:31:57.613Z" }, + { url = "https://files.pythonhosted.org/packages/b7/17/edee1e32215ee6e9e46c3e482645b46575a44a2d72c7dfd49e49f60ce6bf/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", size = 146368, upload-time = "2025-05-02T08:31:59.468Z" }, + { url = "https://files.pythonhosted.org/packages/26/2c/ea3e66f2b5f21fd00b2825c94cafb8c326ea6240cd80a91eb09e4a285830/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", size = 154491, upload-time = "2025-05-02T08:32:01.219Z" }, + { url = "https://files.pythonhosted.org/packages/52/47/7be7fa972422ad062e909fd62460d45c3ef4c141805b7078dbab15904ff7/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", size = 157695, upload-time = "2025-05-02T08:32:03.045Z" }, + { url = "https://files.pythonhosted.org/packages/2f/42/9f02c194da282b2b340f28e5fb60762de1151387a36842a92b533685c61e/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", size = 154849, upload-time = "2025-05-02T08:32:04.651Z" }, + { url = "https://files.pythonhosted.org/packages/67/44/89cacd6628f31fb0b63201a618049be4be2a7435a31b55b5eb1c3674547a/charset_normalizer-3.4.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", size = 150091, upload-time = "2025-05-02T08:32:06.719Z" }, + { url = "https://files.pythonhosted.org/packages/1f/79/4b8da9f712bc079c0f16b6d67b099b0b8d808c2292c937f267d816ec5ecc/charset_normalizer-3.4.2-cp310-cp310-win32.whl", hash = "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", size = 98445, upload-time = "2025-05-02T08:32:08.66Z" }, + { url = "https://files.pythonhosted.org/packages/7d/d7/96970afb4fb66497a40761cdf7bd4f6fca0fc7bafde3a84f836c1f57a926/charset_normalizer-3.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", size = 105782, upload-time = "2025-05-02T08:32:10.46Z" }, + { url = "https://files.pythonhosted.org/packages/05/85/4c40d00dcc6284a1c1ad5de5e0996b06f39d8232f1031cd23c2f5c07ee86/charset_normalizer-3.4.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", size = 198794, upload-time = "2025-05-02T08:32:11.945Z" }, + { url = "https://files.pythonhosted.org/packages/41/d9/7a6c0b9db952598e97e93cbdfcb91bacd89b9b88c7c983250a77c008703c/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", size = 142846, upload-time = "2025-05-02T08:32:13.946Z" }, + { url = "https://files.pythonhosted.org/packages/66/82/a37989cda2ace7e37f36c1a8ed16c58cf48965a79c2142713244bf945c89/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", size = 153350, upload-time = "2025-05-02T08:32:15.873Z" }, + { url = "https://files.pythonhosted.org/packages/df/68/a576b31b694d07b53807269d05ec3f6f1093e9545e8607121995ba7a8313/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", size = 145657, upload-time = "2025-05-02T08:32:17.283Z" }, + { url = "https://files.pythonhosted.org/packages/92/9b/ad67f03d74554bed3aefd56fe836e1623a50780f7c998d00ca128924a499/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f", size = 147260, upload-time = "2025-05-02T08:32:18.807Z" }, + { url = "https://files.pythonhosted.org/packages/a6/e6/8aebae25e328160b20e31a7e9929b1578bbdc7f42e66f46595a432f8539e/charset_normalizer-3.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", size = 149164, upload-time = "2025-05-02T08:32:20.333Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f2/b3c2f07dbcc248805f10e67a0262c93308cfa149a4cd3d1fe01f593e5fd2/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", size = 144571, upload-time = "2025-05-02T08:32:21.86Z" }, + { url = "https://files.pythonhosted.org/packages/60/5b/c3f3a94bc345bc211622ea59b4bed9ae63c00920e2e8f11824aa5708e8b7/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", size = 151952, upload-time = "2025-05-02T08:32:23.434Z" }, + { url = "https://files.pythonhosted.org/packages/e2/4d/ff460c8b474122334c2fa394a3f99a04cf11c646da895f81402ae54f5c42/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", size = 155959, upload-time = "2025-05-02T08:32:24.993Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2b/b964c6a2fda88611a1fe3d4c400d39c66a42d6c169c924818c848f922415/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", size = 153030, upload-time = "2025-05-02T08:32:26.435Z" }, + { url = "https://files.pythonhosted.org/packages/59/2e/d3b9811db26a5ebf444bc0fa4f4be5aa6d76fc6e1c0fd537b16c14e849b6/charset_normalizer-3.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", size = 148015, upload-time = "2025-05-02T08:32:28.376Z" }, + { url = "https://files.pythonhosted.org/packages/90/07/c5fd7c11eafd561bb51220d600a788f1c8d77c5eef37ee49454cc5c35575/charset_normalizer-3.4.2-cp311-cp311-win32.whl", hash = "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", size = 98106, upload-time = "2025-05-02T08:32:30.281Z" }, + { url = "https://files.pythonhosted.org/packages/a8/05/5e33dbef7e2f773d672b6d79f10ec633d4a71cd96db6673625838a4fd532/charset_normalizer-3.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", size = 105402, upload-time = "2025-05-02T08:32:32.191Z" }, + { url = "https://files.pythonhosted.org/packages/d7/a4/37f4d6035c89cac7930395a35cc0f1b872e652eaafb76a6075943754f095/charset_normalizer-3.4.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", size = 199936, upload-time = "2025-05-02T08:32:33.712Z" }, + { url = "https://files.pythonhosted.org/packages/ee/8a/1a5e33b73e0d9287274f899d967907cd0bf9c343e651755d9307e0dbf2b3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", size = 143790, upload-time = "2025-05-02T08:32:35.768Z" }, + { url = "https://files.pythonhosted.org/packages/66/52/59521f1d8e6ab1482164fa21409c5ef44da3e9f653c13ba71becdd98dec3/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", size = 153924, upload-time = "2025-05-02T08:32:37.284Z" }, + { url = "https://files.pythonhosted.org/packages/86/2d/fb55fdf41964ec782febbf33cb64be480a6b8f16ded2dbe8db27a405c09f/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", size = 146626, upload-time = "2025-05-02T08:32:38.803Z" }, + { url = "https://files.pythonhosted.org/packages/8c/73/6ede2ec59bce19b3edf4209d70004253ec5f4e319f9a2e3f2f15601ed5f7/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", size = 148567, upload-time = "2025-05-02T08:32:40.251Z" }, + { url = "https://files.pythonhosted.org/packages/09/14/957d03c6dc343c04904530b6bef4e5efae5ec7d7990a7cbb868e4595ee30/charset_normalizer-3.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", size = 150957, upload-time = "2025-05-02T08:32:41.705Z" }, + { url = "https://files.pythonhosted.org/packages/0d/c8/8174d0e5c10ccebdcb1b53cc959591c4c722a3ad92461a273e86b9f5a302/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", size = 145408, upload-time = "2025-05-02T08:32:43.709Z" }, + { url = "https://files.pythonhosted.org/packages/58/aa/8904b84bc8084ac19dc52feb4f5952c6df03ffb460a887b42615ee1382e8/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", size = 153399, upload-time = "2025-05-02T08:32:46.197Z" }, + { url = "https://files.pythonhosted.org/packages/c2/26/89ee1f0e264d201cb65cf054aca6038c03b1a0c6b4ae998070392a3ce605/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", size = 156815, upload-time = "2025-05-02T08:32:48.105Z" }, + { url = "https://files.pythonhosted.org/packages/fd/07/68e95b4b345bad3dbbd3a8681737b4338ff2c9df29856a6d6d23ac4c73cb/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", size = 154537, upload-time = "2025-05-02T08:32:49.719Z" }, + { url = "https://files.pythonhosted.org/packages/77/1a/5eefc0ce04affb98af07bc05f3bac9094513c0e23b0562d64af46a06aae4/charset_normalizer-3.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", size = 149565, upload-time = "2025-05-02T08:32:51.404Z" }, + { url = "https://files.pythonhosted.org/packages/37/a0/2410e5e6032a174c95e0806b1a6585eb21e12f445ebe239fac441995226a/charset_normalizer-3.4.2-cp312-cp312-win32.whl", hash = "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", size = 98357, upload-time = "2025-05-02T08:32:53.079Z" }, + { url = "https://files.pythonhosted.org/packages/6c/4f/c02d5c493967af3eda9c771ad4d2bbc8df6f99ddbeb37ceea6e8716a32bc/charset_normalizer-3.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", size = 105776, upload-time = "2025-05-02T08:32:54.573Z" }, + { url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" }, + { url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" }, + { url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" }, + { url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" }, + { url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" }, + { url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" }, + { url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" }, + { url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" }, + { url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" }, + { url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" }, + { url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" }, + { url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" }, + { url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" }, + { url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" }, +] + +[[package]] +name = "click" +version = "8.1.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121, upload-time = "2023-08-17T17:29:11.868Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", size = 97941, upload-time = "2023-08-17T17:29:10.08Z" }, +] + +[[package]] +name = "codespell" +version = "2.4.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/e0/709453393c0ea77d007d907dd436b3ee262e28b30995ea1aa36c6ffbccaf/codespell-2.4.1.tar.gz", hash = "sha256:299fcdcb09d23e81e35a671bbe746d5ad7e8385972e65dbb833a2eaac33c01e5", size = 344740, upload-time = "2025-01-28T18:52:39.411Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/01/b394922252051e97aab231d416c86da3d8a6d781eeadcdca1082867de64e/codespell-2.4.1-py3-none-any.whl", hash = "sha256:3dadafa67df7e4a3dbf51e0d7315061b80d265f9552ebd699b3dd6834b47e425", size = 344501, upload-time = "2025-01-28T18:52:37.057Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "constantly" +version = "23.10.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4d/6f/cb2a94494ff74aa9528a36c5b1422756330a75a8367bf20bd63171fc324d/constantly-23.10.4.tar.gz", hash = "sha256:aa92b70a33e2ac0bb33cd745eb61776594dc48764b06c35e0efd050b7f1c7cbd", size = 13300, upload-time = "2023-10-28T23:18:24.316Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/40/c199d095151addf69efdb4b9ca3a4f20f70e20508d6222bffb9b76f58573/constantly-23.10.4-py3-none-any.whl", hash = "sha256:3fd9b4d1c3dc1ec9757f3c52aef7e53ad9323dbe39f51dfd4c43853b68dfa3f9", size = 13547, upload-time = "2023-10-28T23:18:23.038Z" }, +] + +[[package]] +name = "cryptography" +version = "45.0.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "platform_python_implementation != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/1e/49527ac611af559665f71cbb8f92b332b5ec9c6fbc4e88b0f8e92f5e85df/cryptography-45.0.5.tar.gz", hash = "sha256:72e76caa004ab63accdf26023fccd1d087f6d90ec6048ff33ad0445abf7f605a", size = 744903, upload-time = "2025-07-02T13:06:25.941Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f0/fb/09e28bc0c46d2c547085e60897fea96310574c70fb21cd58a730a45f3403/cryptography-45.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:101ee65078f6dd3e5a028d4f19c07ffa4dd22cce6a20eaa160f8b5219911e7d8", size = 7043092, upload-time = "2025-07-02T13:05:01.514Z" }, + { url = "https://files.pythonhosted.org/packages/b1/05/2194432935e29b91fb649f6149c1a4f9e6d3d9fc880919f4ad1bcc22641e/cryptography-45.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3a264aae5f7fbb089dbc01e0242d3b67dffe3e6292e1f5182122bdf58e65215d", size = 4205926, upload-time = "2025-07-02T13:05:04.741Z" }, + { url = "https://files.pythonhosted.org/packages/07/8b/9ef5da82350175e32de245646b1884fc01124f53eb31164c77f95a08d682/cryptography-45.0.5-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e74d30ec9c7cb2f404af331d5b4099a9b322a8a6b25c4632755c8757345baac5", size = 4429235, upload-time = "2025-07-02T13:05:07.084Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e1/c809f398adde1994ee53438912192d92a1d0fc0f2d7582659d9ef4c28b0c/cryptography-45.0.5-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3af26738f2db354aafe492fb3869e955b12b2ef2e16908c8b9cb928128d42c57", size = 4209785, upload-time = "2025-07-02T13:05:09.321Z" }, + { url = "https://files.pythonhosted.org/packages/d0/8b/07eb6bd5acff58406c5e806eff34a124936f41a4fb52909ffa4d00815f8c/cryptography-45.0.5-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e6c00130ed423201c5bc5544c23359141660b07999ad82e34e7bb8f882bb78e0", size = 3893050, upload-time = "2025-07-02T13:05:11.069Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ef/3333295ed58d900a13c92806b67e62f27876845a9a908c939f040887cca9/cryptography-45.0.5-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:dd420e577921c8c2d31289536c386aaa30140b473835e97f83bc71ea9d2baf2d", size = 4457379, upload-time = "2025-07-02T13:05:13.32Z" }, + { url = "https://files.pythonhosted.org/packages/d9/9d/44080674dee514dbb82b21d6fa5d1055368f208304e2ab1828d85c9de8f4/cryptography-45.0.5-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:d05a38884db2ba215218745f0781775806bde4f32e07b135348355fe8e4991d9", size = 4209355, upload-time = "2025-07-02T13:05:15.017Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d8/0749f7d39f53f8258e5c18a93131919ac465ee1f9dccaf1b3f420235e0b5/cryptography-45.0.5-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:ad0caded895a00261a5b4aa9af828baede54638754b51955a0ac75576b831b27", size = 4456087, upload-time = "2025-07-02T13:05:16.945Z" }, + { url = "https://files.pythonhosted.org/packages/09/d7/92acac187387bf08902b0bf0699816f08553927bdd6ba3654da0010289b4/cryptography-45.0.5-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9024beb59aca9d31d36fcdc1604dd9bbeed0a55bface9f1908df19178e2f116e", size = 4332873, upload-time = "2025-07-02T13:05:18.743Z" }, + { url = "https://files.pythonhosted.org/packages/03/c2/840e0710da5106a7c3d4153c7215b2736151bba60bf4491bdb421df5056d/cryptography-45.0.5-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:91098f02ca81579c85f66df8a588c78f331ca19089763d733e34ad359f474174", size = 4564651, upload-time = "2025-07-02T13:05:21.382Z" }, + { url = "https://files.pythonhosted.org/packages/2e/92/cc723dd6d71e9747a887b94eb3827825c6c24b9e6ce2bb33b847d31d5eaa/cryptography-45.0.5-cp311-abi3-win32.whl", hash = "sha256:926c3ea71a6043921050eaa639137e13dbe7b4ab25800932a8498364fc1abec9", size = 2929050, upload-time = "2025-07-02T13:05:23.39Z" }, + { url = "https://files.pythonhosted.org/packages/1f/10/197da38a5911a48dd5389c043de4aec4b3c94cb836299b01253940788d78/cryptography-45.0.5-cp311-abi3-win_amd64.whl", hash = "sha256:b85980d1e345fe769cfc57c57db2b59cff5464ee0c045d52c0df087e926fbe63", size = 3403224, upload-time = "2025-07-02T13:05:25.202Z" }, + { url = "https://files.pythonhosted.org/packages/fe/2b/160ce8c2765e7a481ce57d55eba1546148583e7b6f85514472b1d151711d/cryptography-45.0.5-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:f3562c2f23c612f2e4a6964a61d942f891d29ee320edb62ff48ffb99f3de9ae8", size = 7017143, upload-time = "2025-07-02T13:05:27.229Z" }, + { url = "https://files.pythonhosted.org/packages/c2/e7/2187be2f871c0221a81f55ee3105d3cf3e273c0a0853651d7011eada0d7e/cryptography-45.0.5-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3fcfbefc4a7f332dece7272a88e410f611e79458fab97b5efe14e54fe476f4fd", size = 4197780, upload-time = "2025-07-02T13:05:29.299Z" }, + { url = "https://files.pythonhosted.org/packages/b9/cf/84210c447c06104e6be9122661159ad4ce7a8190011669afceeaea150524/cryptography-45.0.5-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:460f8c39ba66af7db0545a8c6f2eabcbc5a5528fc1cf6c3fa9a1e44cec33385e", size = 4420091, upload-time = "2025-07-02T13:05:31.221Z" }, + { url = "https://files.pythonhosted.org/packages/3e/6a/cb8b5c8bb82fafffa23aeff8d3a39822593cee6e2f16c5ca5c2ecca344f7/cryptography-45.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:9b4cf6318915dccfe218e69bbec417fdd7c7185aa7aab139a2c0beb7468c89f0", size = 4198711, upload-time = "2025-07-02T13:05:33.062Z" }, + { url = "https://files.pythonhosted.org/packages/04/f7/36d2d69df69c94cbb2473871926daf0f01ad8e00fe3986ac3c1e8c4ca4b3/cryptography-45.0.5-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2089cc8f70a6e454601525e5bf2779e665d7865af002a5dec8d14e561002e135", size = 3883299, upload-time = "2025-07-02T13:05:34.94Z" }, + { url = "https://files.pythonhosted.org/packages/82/c7/f0ea40f016de72f81288e9fe8d1f6748036cb5ba6118774317a3ffc6022d/cryptography-45.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:0027d566d65a38497bc37e0dd7c2f8ceda73597d2ac9ba93810204f56f52ebc7", size = 4450558, upload-time = "2025-07-02T13:05:37.288Z" }, + { url = "https://files.pythonhosted.org/packages/06/ae/94b504dc1a3cdf642d710407c62e86296f7da9e66f27ab12a1ee6fdf005b/cryptography-45.0.5-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:be97d3a19c16a9be00edf79dca949c8fa7eff621763666a145f9f9535a5d7f42", size = 4198020, upload-time = "2025-07-02T13:05:39.102Z" }, + { url = "https://files.pythonhosted.org/packages/05/2b/aaf0adb845d5dabb43480f18f7ca72e94f92c280aa983ddbd0bcd6ecd037/cryptography-45.0.5-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:7760c1c2e1a7084153a0f68fab76e754083b126a47d0117c9ed15e69e2103492", size = 4449759, upload-time = "2025-07-02T13:05:41.398Z" }, + { url = "https://files.pythonhosted.org/packages/91/e4/f17e02066de63e0100a3a01b56f8f1016973a1d67551beaf585157a86b3f/cryptography-45.0.5-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6ff8728d8d890b3dda5765276d1bc6fb099252915a2cd3aff960c4c195745dd0", size = 4319991, upload-time = "2025-07-02T13:05:43.64Z" }, + { url = "https://files.pythonhosted.org/packages/f2/2e/e2dbd629481b499b14516eed933f3276eb3239f7cee2dcfa4ee6b44d4711/cryptography-45.0.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:7259038202a47fdecee7e62e0fd0b0738b6daa335354396c6ddebdbe1206af2a", size = 4554189, upload-time = "2025-07-02T13:05:46.045Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ea/a78a0c38f4c8736287b71c2ea3799d173d5ce778c7d6e3c163a95a05ad2a/cryptography-45.0.5-cp37-abi3-win32.whl", hash = "sha256:1e1da5accc0c750056c556a93c3e9cb828970206c68867712ca5805e46dc806f", size = 2911769, upload-time = "2025-07-02T13:05:48.329Z" }, + { url = "https://files.pythonhosted.org/packages/79/b3/28ac139109d9005ad3f6b6f8976ffede6706a6478e21c889ce36c840918e/cryptography-45.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:90cb0a7bb35959f37e23303b7eed0a32280510030daba3f7fdfbb65defde6a97", size = 3390016, upload-time = "2025-07-02T13:05:50.811Z" }, + { url = "https://files.pythonhosted.org/packages/f8/8b/34394337abe4566848a2bd49b26bcd4b07fd466afd3e8cce4cb79a390869/cryptography-45.0.5-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:206210d03c1193f4e1ff681d22885181d47efa1ab3018766a7b32a7b3d6e6afd", size = 3575762, upload-time = "2025-07-02T13:05:53.166Z" }, + { url = "https://files.pythonhosted.org/packages/8b/5d/a19441c1e89afb0f173ac13178606ca6fab0d3bd3ebc29e9ed1318b507fc/cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c648025b6840fe62e57107e0a25f604db740e728bd67da4f6f060f03017d5097", size = 4140906, upload-time = "2025-07-02T13:05:55.914Z" }, + { url = "https://files.pythonhosted.org/packages/4b/db/daceb259982a3c2da4e619f45b5bfdec0e922a23de213b2636e78ef0919b/cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b8fa8b0a35a9982a3c60ec79905ba5bb090fc0b9addcfd3dc2dd04267e45f25e", size = 4374411, upload-time = "2025-07-02T13:05:57.814Z" }, + { url = "https://files.pythonhosted.org/packages/6a/35/5d06ad06402fc522c8bf7eab73422d05e789b4e38fe3206a85e3d6966c11/cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:14d96584701a887763384f3c47f0ca7c1cce322aa1c31172680eb596b890ec30", size = 4140942, upload-time = "2025-07-02T13:06:00.137Z" }, + { url = "https://files.pythonhosted.org/packages/65/79/020a5413347e44c382ef1f7f7e7a66817cd6273e3e6b5a72d18177b08b2f/cryptography-45.0.5-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:57c816dfbd1659a367831baca4b775b2a5b43c003daf52e9d57e1d30bc2e1b0e", size = 4374079, upload-time = "2025-07-02T13:06:02.043Z" }, + { url = "https://files.pythonhosted.org/packages/9b/c5/c0e07d84a9a2a8a0ed4f865e58f37c71af3eab7d5e094ff1b21f3f3af3bc/cryptography-45.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b9e38e0a83cd51e07f5a48ff9691cae95a79bea28fe4ded168a8e5c6c77e819d", size = 3321362, upload-time = "2025-07-02T13:06:04.463Z" }, + { url = "https://files.pythonhosted.org/packages/c0/71/9bdbcfd58d6ff5084687fe722c58ac718ebedbc98b9f8f93781354e6d286/cryptography-45.0.5-pp311-pypy311_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8c4a6ff8a30e9e3d38ac0539e9a9e02540ab3f827a3394f8852432f6b0ea152e", size = 3587878, upload-time = "2025-07-02T13:06:06.339Z" }, + { url = "https://files.pythonhosted.org/packages/f0/63/83516cfb87f4a8756eaa4203f93b283fda23d210fc14e1e594bd5f20edb6/cryptography-45.0.5-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:bd4c45986472694e5121084c6ebbd112aa919a25e783b87eb95953c9573906d6", size = 4152447, upload-time = "2025-07-02T13:06:08.345Z" }, + { url = "https://files.pythonhosted.org/packages/22/11/d2823d2a5a0bd5802b3565437add16f5c8ce1f0778bf3822f89ad2740a38/cryptography-45.0.5-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:982518cd64c54fcada9d7e5cf28eabd3ee76bd03ab18e08a48cad7e8b6f31b18", size = 4386778, upload-time = "2025-07-02T13:06:10.263Z" }, + { url = "https://files.pythonhosted.org/packages/5f/38/6bf177ca6bce4fe14704ab3e93627c5b0ca05242261a2e43ef3168472540/cryptography-45.0.5-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:12e55281d993a793b0e883066f590c1ae1e802e3acb67f8b442e721e475e6463", size = 4151627, upload-time = "2025-07-02T13:06:13.097Z" }, + { url = "https://files.pythonhosted.org/packages/38/6a/69fc67e5266bff68a91bcb81dff8fb0aba4d79a78521a08812048913e16f/cryptography-45.0.5-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:5aa1e32983d4443e310f726ee4b071ab7569f58eedfdd65e9675484a4eb67bd1", size = 4385593, upload-time = "2025-07-02T13:06:15.689Z" }, + { url = "https://files.pythonhosted.org/packages/f6/34/31a1604c9a9ade0fdab61eb48570e09a796f4d9836121266447b0eaf7feb/cryptography-45.0.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:e357286c1b76403dd384d938f93c46b2b058ed4dfcdce64a770f0537ed3feb6f", size = 3331106, upload-time = "2025-07-02T13:06:18.058Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, +] + +[[package]] +name = "execnet" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/ff/b4c0dc78fbe20c3e59c0c7334de0c27eb4001a2b2017999af398bf730817/execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3", size = 166524, upload-time = "2024-04-08T09:04:19.245Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612, upload-time = "2024-04-08T09:04:17.414Z" }, +] + +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "hyperlink" +version = "21.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3a/51/1947bd81d75af87e3bb9e34593a4cf118115a8feb451ce7a69044ef1412e/hyperlink-21.0.0.tar.gz", hash = "sha256:427af957daa58bc909471c6c40f74c5450fa123dd093fc53efd2e91d2705a56b", size = 140743, upload-time = "2021-01-08T05:51:20.972Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6e/aa/8caf6a0a3e62863cbb9dab27135660acba46903b703e224f14f447e57934/hyperlink-21.0.0-py2.py3-none-any.whl", hash = "sha256:e6b14c37ecb73e89c77d78cdb4c2cc8f3fb59a885c5b3f819ff4ed80f25af1b4", size = 74638, upload-time = "2021-01-08T05:51:22.906Z" }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "incremental" +version = "24.7.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "setuptools" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/27/87/156b374ff6578062965afe30cc57627d35234369b3336cf244b240c8d8e6/incremental-24.7.2.tar.gz", hash = "sha256:fb4f1d47ee60efe87d4f6f0ebb5f70b9760db2b2574c59c8e8912be4ebd464c9", size = 28157, upload-time = "2024-07-29T20:03:55.441Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/38/221e5b2ae676a3938c2c1919131410c342b6efc2baffeda395dd66eeca8f/incremental-24.7.2-py3-none-any.whl", hash = "sha256:8cb2c3431530bec48ad70513931a760f446ad6c25e8333ca5d95e24b0ed7b8fe", size = 20516, upload-time = "2024-07-29T20:03:53.677Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, +] + +[[package]] +name = "isort" +version = "6.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/21/1e2a441f74a653a144224d7d21afe8f4169e6c7c20bb13aec3a2dc3815e0/isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450", size = 821955, upload-time = "2025-02-26T21:13:16.955Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/11/114d0a5f4dabbdcedc1125dee0888514c3c3b16d3e9facad87ed96fad97c/isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615", size = 94186, upload-time = "2025-02-26T21:13:14.911Z" }, +] + +[[package]] +name = "jsondiff" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/35/48/841137f1843fa215ea284834d1514b8e9e20962bda63a636c7417e02f8fb/jsondiff-2.2.1.tar.gz", hash = "sha256:658d162c8a86ba86de26303cd86a7b37e1b2c1ec98b569a60e2ca6180545f7fe", size = 26649, upload-time = "2024-08-29T04:09:06.201Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/94/a8066f84d62ab666d61ef97deba1a33126e3e5c0c0da2c458ada17053ed6/jsondiff-2.2.1-py3-none-any.whl", hash = "sha256:b1f0f7e2421881848b1d556d541ac01a91680cfcc14f51a9b62cdf4da0e56722", size = 13440, upload-time = "2024-08-29T04:09:04.955Z" }, +] + +[[package]] +name = "marshmallow" +version = "3.26.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ab/5e/5e53d26b42ab75491cda89b871dab9e97c840bf12c63ec58a1919710cd06/marshmallow-3.26.1.tar.gz", hash = "sha256:e6d8affb6cb61d39d26402096dc0aee12d5a26d490a121f118d2e81dc0719dc6", size = 221825, upload-time = "2025-02-03T15:32:25.093Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl", hash = "sha256:3350409f20a70a7e4e11a27661187b77cdcaeb20abca41c1454fe33636bea09c", size = 50878, upload-time = "2025-02-03T15:32:22.295Z" }, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "platformio" +version = "6.2.0" +source = { virtual = "." } +dependencies = [ + { name = "ajsonrpc" }, + { name = "bottle" }, + { name = "chardet", marker = "'arm' in platform_machine and sys_platform == 'darwin'" }, + { name = "click" }, + { name = "colorama" }, + { name = "constantly" }, + { name = "marshmallow" }, + { name = "pyelftools" }, + { name = "pyopenssl" }, + { name = "pyserial" }, + { name = "requests", extra = ["socks"] }, + { name = "semantic-version" }, + { name = "service-identity" }, + { name = "starlette" }, + { name = "tabulate" }, + { name = "twisted" }, + { name = "urllib3" }, + { name = "uvicorn" }, + { name = "wsproto" }, +] + +[package.optional-dependencies] +dev = [ + { name = "codespell" }, + { name = "isort" }, + { name = "jsondiff" }, + { name = "pyright" }, + { name = "pytest" }, + { name = "pytest-xdist" }, + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [ + { name = "ajsonrpc", specifier = "==1.2.*" }, + { name = "bottle", specifier = "==0.13.*" }, + { name = "chardet", marker = "'arm' in platform_machine and sys_platform == 'darwin'", specifier = ">=3.0.2,<6" }, + { name = "click", specifier = ">=8.0.4,<8.1.8" }, + { name = "codespell", marker = "extra == 'dev'" }, + { name = "colorama" }, + { name = "constantly", specifier = ">=23.10.4" }, + { name = "isort", marker = "extra == 'dev'" }, + { name = "jsondiff", marker = "extra == 'dev'" }, + { name = "marshmallow", specifier = "==3.*" }, + { name = "pyelftools", specifier = ">=0.27,<1" }, + { name = "pyopenssl", specifier = ">=25.1.0" }, + { name = "pyright", marker = "extra == 'dev'" }, + { name = "pyserial", specifier = "==3.5.*" }, + { name = "pytest", marker = "extra == 'dev'" }, + { name = "pytest-xdist", marker = "extra == 'dev'" }, + { name = "requests", extras = ["socks"], specifier = "==2.*" }, + { name = "ruff", marker = "extra == 'dev'" }, + { name = "semantic-version", specifier = "==2.10.*" }, + { name = "service-identity", specifier = ">=24.2.0" }, + { name = "starlette", specifier = ">=0.19,<0.47" }, + { name = "tabulate", specifier = "==0.*" }, + { name = "twisted", specifier = ">=25.5.0" }, + { name = "urllib3", specifier = "<2" }, + { name = "uvicorn", specifier = ">=0.16,<0.35" }, + { name = "wsproto", specifier = "==1.*" }, +] +provides-extras = ["dev"] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pyasn1" +version = "0.6.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" }, +] + +[[package]] +name = "pyasn1-modules" +version = "0.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyasn1" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" }, +] + +[[package]] +name = "pycparser" +version = "2.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" }, +] + +[[package]] +name = "pyelftools" +version = "0.32" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/ab/33968940b2deb3d92f5b146bc6d4009a5f95d1d06c148ea2f9ee965071af/pyelftools-0.32.tar.gz", hash = "sha256:6de90ee7b8263e740c8715a925382d4099b354f29ac48ea40d840cf7aa14ace5", size = 15047199, upload-time = "2025-02-19T14:20:05.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/43/700932c4f0638c3421177144a2e86448c0d75dbaee2c7936bda3f9fd0878/pyelftools-0.32-py3-none-any.whl", hash = "sha256:013df952a006db5e138b1edf6d8a68ecc50630adbd0d83a2d41e7f846163d738", size = 188525, upload-time = "2025-02-19T14:19:59.919Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pyopenssl" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cryptography" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/8c/cd89ad05804f8e3c17dea8f178c3f40eeab5694c30e0c9f5bcd49f576fc3/pyopenssl-25.1.0.tar.gz", hash = "sha256:8d031884482e0c67ee92bf9a4d8cceb08d92aba7136432ffb0703c5280fc205b", size = 179937, upload-time = "2025-05-17T16:28:31.31Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/80/28/2659c02301b9500751f8d42f9a6632e1508aa5120de5e43042b8b30f8d5d/pyopenssl-25.1.0-py3-none-any.whl", hash = "sha256:2b11f239acc47ac2e5aca04fd7fa829800aeee22a2eb30d744572a157bd8a1ab", size = 56771, upload-time = "2025-05-17T16:28:29.197Z" }, +] + +[[package]] +name = "pyright" +version = "1.1.402" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "nodeenv" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/aa/04/ce0c132d00e20f2d2fb3b3e7c125264ca8b909e693841210534b1ea1752f/pyright-1.1.402.tar.gz", hash = "sha256:85a33c2d40cd4439c66aa946fd4ce71ab2f3f5b8c22ce36a623f59ac22937683", size = 3888207, upload-time = "2025-06-11T08:48:35.759Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/37/1a1c62d955e82adae588be8e374c7f77b165b6cb4203f7d581269959abbc/pyright-1.1.402-py3-none-any.whl", hash = "sha256:2c721f11869baac1884e846232800fe021c33f1b4acb3929cff321f7ea4e2982", size = 5624004, upload-time = "2025-06-11T08:48:33.998Z" }, +] + +[[package]] +name = "pyserial" +version = "3.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/7d/ae3f0a63f41e4d2f6cb66a5b57197850f919f59e558159a4dd3a818f5082/pyserial-3.5.tar.gz", hash = "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", size = 159125, upload-time = "2020-11-23T03:59:15.045Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/bc/587a445451b253b285629263eb51c2d8e9bcea4fc97826266d186f96f558/pyserial-3.5-py2.py3-none-any.whl", hash = "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0", size = 90585, upload-time = "2020-11-23T03:59:13.41Z" }, +] + +[[package]] +name = "pysocks" +version = "1.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/11/293dd436aea955d45fc4e8a35b6ae7270f5b8e00b53cf6c024c83b657a11/PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0", size = 284429, upload-time = "2019-09-20T02:07:35.714Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", size = 16725, upload-time = "2019-09-20T02:06:22.938Z" }, +] + +[[package]] +name = "pytest" +version = "8.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/ba/45911d754e8eba3d5a841a5ce61a65a685ff1798421ac054f85aa8747dfb/pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c", size = 1517714, upload-time = "2025-06-18T05:48:06.109Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/29/16/c8a903f4c4dffe7a12843191437d7cd8e32751d5de349d45d3fe69544e87/pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", size = 365474, upload-time = "2025-06-18T05:48:03.955Z" }, +] + +[[package]] +name = "pytest-xdist" +version = "3.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/b4/439b179d1ff526791eb921115fca8e44e596a13efeda518b9d845a619450/pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1", size = 88069, upload-time = "2025-07-01T13:30:59.346Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/31/d4e37e9e550c2b92a9cbc2e4d0b7420a27224968580b5a447f420847c975/pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", size = 46396, upload-time = "2025-07-01T13:30:56.632Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199, upload-time = "2024-08-06T20:31:40.178Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758, upload-time = "2024-08-06T20:31:42.173Z" }, + { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463, upload-time = "2024-08-06T20:31:44.263Z" }, + { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280, upload-time = "2024-08-06T20:31:50.199Z" }, + { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239, upload-time = "2024-08-06T20:31:52.292Z" }, + { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802, upload-time = "2024-08-06T20:31:53.836Z" }, + { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527, upload-time = "2024-08-06T20:31:55.565Z" }, + { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052, upload-time = "2024-08-06T20:31:56.914Z" }, + { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774, upload-time = "2024-08-06T20:31:58.304Z" }, + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, +] + +[[package]] +name = "requests" +version = "2.32.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, +] + +[package.optional-dependencies] +socks = [ + { name = "pysocks" }, +] + +[[package]] +name = "ruff" +version = "0.12.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/3d/d9a195676f25d00dbfcf3cf95fdd4c685c497fcfa7e862a44ac5e4e96480/ruff-0.12.2.tar.gz", hash = "sha256:d7b4f55cd6f325cb7621244f19c873c565a08aff5a4ba9c69aa7355f3f7afd3e", size = 4432239, upload-time = "2025-07-03T16:40:19.566Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/b6/2098d0126d2d3318fd5bec3ad40d06c25d377d95749f7a0c5af17129b3b1/ruff-0.12.2-py3-none-linux_armv6l.whl", hash = "sha256:093ea2b221df1d2b8e7ad92fc6ffdca40a2cb10d8564477a987b44fd4008a7be", size = 10369761, upload-time = "2025-07-03T16:39:38.847Z" }, + { url = "https://files.pythonhosted.org/packages/b1/4b/5da0142033dbe155dc598cfb99262d8ee2449d76920ea92c4eeb9547c208/ruff-0.12.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:09e4cf27cc10f96b1708100fa851e0daf21767e9709e1649175355280e0d950e", size = 11155659, upload-time = "2025-07-03T16:39:42.294Z" }, + { url = "https://files.pythonhosted.org/packages/3e/21/967b82550a503d7c5c5c127d11c935344b35e8c521f52915fc858fb3e473/ruff-0.12.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8ae64755b22f4ff85e9c52d1f82644abd0b6b6b6deedceb74bd71f35c24044cc", size = 10537769, upload-time = "2025-07-03T16:39:44.75Z" }, + { url = "https://files.pythonhosted.org/packages/33/91/00cff7102e2ec71a4890fb7ba1803f2cdb122d82787c7d7cf8041fe8cbc1/ruff-0.12.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eb3a6b2db4d6e2c77e682f0b988d4d61aff06860158fdb413118ca133d57922", size = 10717602, upload-time = "2025-07-03T16:39:47.652Z" }, + { url = "https://files.pythonhosted.org/packages/9b/eb/928814daec4e1ba9115858adcda44a637fb9010618721937491e4e2283b8/ruff-0.12.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73448de992d05517170fc37169cbca857dfeaeaa8c2b9be494d7bcb0d36c8f4b", size = 10198772, upload-time = "2025-07-03T16:39:49.641Z" }, + { url = "https://files.pythonhosted.org/packages/50/fa/f15089bc20c40f4f72334f9145dde55ab2b680e51afb3b55422effbf2fb6/ruff-0.12.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b8b94317cbc2ae4a2771af641739f933934b03555e51515e6e021c64441532d", size = 11845173, upload-time = "2025-07-03T16:39:52.069Z" }, + { url = "https://files.pythonhosted.org/packages/43/9f/1f6f98f39f2b9302acc161a4a2187b1e3a97634fe918a8e731e591841cf4/ruff-0.12.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:45fc42c3bf1d30d2008023a0a9a0cfb06bf9835b147f11fe0679f21ae86d34b1", size = 12553002, upload-time = "2025-07-03T16:39:54.551Z" }, + { url = "https://files.pythonhosted.org/packages/d8/70/08991ac46e38ddd231c8f4fd05ef189b1b94be8883e8c0c146a025c20a19/ruff-0.12.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce48f675c394c37e958bf229fb5c1e843e20945a6d962cf3ea20b7a107dcd9f4", size = 12171330, upload-time = "2025-07-03T16:39:57.55Z" }, + { url = "https://files.pythonhosted.org/packages/88/a9/5a55266fec474acfd0a1c73285f19dd22461d95a538f29bba02edd07a5d9/ruff-0.12.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793d8859445ea47591272021a81391350205a4af65a9392401f418a95dfb75c9", size = 11774717, upload-time = "2025-07-03T16:39:59.78Z" }, + { url = "https://files.pythonhosted.org/packages/87/e5/0c270e458fc73c46c0d0f7cf970bb14786e5fdb88c87b5e423a4bd65232b/ruff-0.12.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6932323db80484dda89153da3d8e58164d01d6da86857c79f1961934354992da", size = 11646659, upload-time = "2025-07-03T16:40:01.934Z" }, + { url = "https://files.pythonhosted.org/packages/b7/b6/45ab96070c9752af37f0be364d849ed70e9ccede07675b0ec4e3ef76b63b/ruff-0.12.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6aa7e623a3a11538108f61e859ebf016c4f14a7e6e4eba1980190cacb57714ce", size = 10604012, upload-time = "2025-07-03T16:40:04.363Z" }, + { url = "https://files.pythonhosted.org/packages/86/91/26a6e6a424eb147cc7627eebae095cfa0b4b337a7c1c413c447c9ebb72fd/ruff-0.12.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:2a4a20aeed74671b2def096bdf2eac610c7d8ffcbf4fb0e627c06947a1d7078d", size = 10176799, upload-time = "2025-07-03T16:40:06.514Z" }, + { url = "https://files.pythonhosted.org/packages/f5/0c/9f344583465a61c8918a7cda604226e77b2c548daf8ef7c2bfccf2b37200/ruff-0.12.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:71a4c550195612f486c9d1f2b045a600aeba851b298c667807ae933478fcef04", size = 11241507, upload-time = "2025-07-03T16:40:08.708Z" }, + { url = "https://files.pythonhosted.org/packages/1c/b7/99c34ded8fb5f86c0280278fa89a0066c3760edc326e935ce0b1550d315d/ruff-0.12.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:4987b8f4ceadf597c927beee65a5eaf994c6e2b631df963f86d8ad1bdea99342", size = 11717609, upload-time = "2025-07-03T16:40:10.836Z" }, + { url = "https://files.pythonhosted.org/packages/51/de/8589fa724590faa057e5a6d171e7f2f6cffe3287406ef40e49c682c07d89/ruff-0.12.2-py3-none-win32.whl", hash = "sha256:369ffb69b70cd55b6c3fc453b9492d98aed98062db9fec828cdfd069555f5f1a", size = 10523823, upload-time = "2025-07-03T16:40:13.203Z" }, + { url = "https://files.pythonhosted.org/packages/94/47/8abf129102ae4c90cba0c2199a1a9b0fa896f6f806238d6f8c14448cc748/ruff-0.12.2-py3-none-win_amd64.whl", hash = "sha256:dca8a3b6d6dc9810ed8f328d406516bf4d660c00caeaef36eb831cf4871b0639", size = 11629831, upload-time = "2025-07-03T16:40:15.478Z" }, + { url = "https://files.pythonhosted.org/packages/e2/1f/72d2946e3cc7456bb837e88000eb3437e55f80db339c840c04015a11115d/ruff-0.12.2-py3-none-win_arm64.whl", hash = "sha256:48d6c6bfb4761df68bc05ae630e24f506755e702d4fb08f08460be778c7ccb12", size = 10735334, upload-time = "2025-07-03T16:40:17.677Z" }, +] + +[[package]] +name = "semantic-version" +version = "2.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/31/f2289ce78b9b473d582568c234e104d2a342fd658cc288a7553d83bb8595/semantic_version-2.10.0.tar.gz", hash = "sha256:bdabb6d336998cbb378d4b9db3a4b56a1e3235701dc05ea2690d9a997ed5041c", size = 52289, upload-time = "2022-05-26T13:35:23.454Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/23/8146aad7d88f4fcb3a6218f41a60f6c2d4e3a72de72da1825dc7c8f7877c/semantic_version-2.10.0-py2.py3-none-any.whl", hash = "sha256:de78a3b8e0feda74cabc54aab2da702113e33ac9d9eb9d2389bcf1f58b7d9177", size = 15552, upload-time = "2022-05-26T13:35:21.206Z" }, +] + +[[package]] +name = "service-identity" +version = "24.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "cryptography" }, + { name = "pyasn1" }, + { name = "pyasn1-modules" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/a5/dfc752b979067947261dbbf2543470c58efe735c3c1301dd870ef27830ee/service_identity-24.2.0.tar.gz", hash = "sha256:b8683ba13f0d39c6cd5d625d2c5f65421d6d707b013b375c355751557cbe8e09", size = 39245, upload-time = "2024-10-26T07:21:57.736Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/2c/ca6dd598b384bc1ce581e24aaae0f2bed4ccac57749d5c3befbb5e742081/service_identity-24.2.0-py3-none-any.whl", hash = "sha256:6b047fbd8a84fd0bb0d55ebce4031e400562b9196e1e0d3e0fe2b8a59f6d4a85", size = 11364, upload-time = "2024-10-26T07:21:56.302Z" }, +] + +[[package]] +name = "setuptools" +version = "80.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" }, +] + +[[package]] +name = "starlette" +version = "0.46.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ce/20/08dfcd9c983f6a6f4a1000d934b9e6d626cff8d2eeb77a89a68eef20a2b7/starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5", size = 2580846, upload-time = "2025-04-13T13:56:17.942Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037, upload-time = "2025-04-13T13:56:16.21Z" }, +] + +[[package]] +name = "tabulate" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090, upload-time = "2022-10-06T17:21:48.54Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252, upload-time = "2022-10-06T17:21:44.262Z" }, +] + +[[package]] +name = "tomli" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, +] + +[[package]] +name = "twisted" +version = "25.5.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "automat" }, + { name = "constantly" }, + { name = "hyperlink" }, + { name = "incremental" }, + { name = "typing-extensions" }, + { name = "zope-interface" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/13/0f/82716ed849bf7ea4984c21385597c949944f0f9b428b5710f79d0afc084d/twisted-25.5.0.tar.gz", hash = "sha256:1deb272358cb6be1e3e8fc6f9c8b36f78eb0fa7c2233d2dbe11ec6fee04ea316", size = 3545725, upload-time = "2025-06-07T09:52:24.858Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/66/ab7efd8941f0bc7b2bd555b0f0471bff77df4c88e0cc31120c82737fec77/twisted-25.5.0-py3-none-any.whl", hash = "sha256:8559f654d01a54a8c3efe66d533d43f383531ebf8d81d9f9ab4769d91ca15df7", size = 3204767, upload-time = "2025-06-07T09:52:21.428Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.14.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" }, +] + +[[package]] +name = "urllib3" +version = "1.26.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/e8/6ff5e6bc22095cfc59b6ea711b687e2b7ed4bdb373f7eeec370a97d7392f/urllib3-1.26.20.tar.gz", hash = "sha256:40c2dc0c681e47eb8f90e7e27bf6ff7df2e677421fd46756da1161c39ca70d32", size = 307380, upload-time = "2024-08-29T15:43:11.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/cf/8435d5a7159e2a9c83a95896ed596f68cf798005fe107cc655b5c5c14704/urllib3-1.26.20-py2.py3-none-any.whl", hash = "sha256:0ed14ccfbf1c30a9072c7ca157e4319b70d65f623e91e7b32fadb2853431016e", size = 144225, upload-time = "2024-08-29T15:43:08.921Z" }, +] + +[[package]] +name = "uvicorn" +version = "0.34.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "h11" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/de/ad/713be230bcda622eaa35c28f0d328c3675c371238470abdea52417f17a8e/uvicorn-0.34.3.tar.gz", hash = "sha256:35919a9a979d7a59334b6b10e05d77c1d0d574c50e0fc98b8b1a0f165708b55a", size = 76631, upload-time = "2025-06-01T07:48:17.531Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/0d/8adfeaa62945f90d19ddc461c55f4a50c258af7662d34b6a3d5d1f8646f6/uvicorn-0.34.3-py3-none-any.whl", hash = "sha256:16246631db62bdfbf069b0645177d6e8a77ba950cfedbfd093acef9444e4d885", size = 62431, upload-time = "2025-06-01T07:48:15.664Z" }, +] + +[[package]] +name = "wsproto" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425, upload-time = "2022-08-23T19:58:21.447Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226, upload-time = "2022-08-23T19:58:19.96Z" }, +] + +[[package]] +name = "zope-interface" +version = "7.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "setuptools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/93/9210e7606be57a2dfc6277ac97dcc864fd8d39f142ca194fdc186d596fda/zope.interface-7.2.tar.gz", hash = "sha256:8b49f1a3d1ee4cdaf5b32d2e738362c7f5e40ac8b46dd7d1a65e82a4872728fe", size = 252960, upload-time = "2024-11-28T08:45:39.224Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/71/e6177f390e8daa7e75378505c5ab974e0bf59c1d3b19155638c7afbf4b2d/zope.interface-7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ce290e62229964715f1011c3dbeab7a4a1e4971fd6f31324c4519464473ef9f2", size = 208243, upload-time = "2024-11-28T08:47:29.781Z" }, + { url = "https://files.pythonhosted.org/packages/52/db/7e5f4226bef540f6d55acfd95cd105782bc6ee044d9b5587ce2c95558a5e/zope.interface-7.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:05b910a5afe03256b58ab2ba6288960a2892dfeef01336dc4be6f1b9ed02ab0a", size = 208759, upload-time = "2024-11-28T08:47:31.908Z" }, + { url = "https://files.pythonhosted.org/packages/28/ea/fdd9813c1eafd333ad92464d57a4e3a82b37ae57c19497bcffa42df673e4/zope.interface-7.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:550f1c6588ecc368c9ce13c44a49b8d6b6f3ca7588873c679bd8fd88a1b557b6", size = 254922, upload-time = "2024-11-28T09:18:11.795Z" }, + { url = "https://files.pythonhosted.org/packages/3b/d3/0000a4d497ef9fbf4f66bb6828b8d0a235e690d57c333be877bec763722f/zope.interface-7.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ef9e2f865721553c6f22a9ff97da0f0216c074bd02b25cf0d3af60ea4d6931d", size = 249367, upload-time = "2024-11-28T08:48:24.238Z" }, + { url = "https://files.pythonhosted.org/packages/3e/e5/0b359e99084f033d413419eff23ee9c2bd33bca2ca9f4e83d11856f22d10/zope.interface-7.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27f926f0dcb058211a3bb3e0e501c69759613b17a553788b2caeb991bed3b61d", size = 254488, upload-time = "2024-11-28T08:48:28.816Z" }, + { url = "https://files.pythonhosted.org/packages/7b/90/12d50b95f40e3b2fc0ba7f7782104093b9fd62806b13b98ef4e580f2ca61/zope.interface-7.2-cp310-cp310-win_amd64.whl", hash = "sha256:144964649eba4c5e4410bb0ee290d338e78f179cdbfd15813de1a664e7649b3b", size = 211947, upload-time = "2024-11-28T08:48:18.831Z" }, + { url = "https://files.pythonhosted.org/packages/98/7d/2e8daf0abea7798d16a58f2f3a2bf7588872eee54ac119f99393fdd47b65/zope.interface-7.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1909f52a00c8c3dcab6c4fad5d13de2285a4b3c7be063b239b8dc15ddfb73bd2", size = 208776, upload-time = "2024-11-28T08:47:53.009Z" }, + { url = "https://files.pythonhosted.org/packages/a0/2a/0c03c7170fe61d0d371e4c7ea5b62b8cb79b095b3d630ca16719bf8b7b18/zope.interface-7.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:80ecf2451596f19fd607bb09953f426588fc1e79e93f5968ecf3367550396b22", size = 209296, upload-time = "2024-11-28T08:47:57.993Z" }, + { url = "https://files.pythonhosted.org/packages/49/b4/451f19448772b4a1159519033a5f72672221e623b0a1bd2b896b653943d8/zope.interface-7.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:033b3923b63474800b04cba480b70f6e6243a62208071fc148354f3f89cc01b7", size = 260997, upload-time = "2024-11-28T09:18:13.935Z" }, + { url = "https://files.pythonhosted.org/packages/65/94/5aa4461c10718062c8f8711161faf3249d6d3679c24a0b81dd6fc8ba1dd3/zope.interface-7.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a102424e28c6b47c67923a1f337ede4a4c2bba3965b01cf707978a801fc7442c", size = 255038, upload-time = "2024-11-28T08:48:26.381Z" }, + { url = "https://files.pythonhosted.org/packages/9f/aa/1a28c02815fe1ca282b54f6705b9ddba20328fabdc37b8cf73fc06b172f0/zope.interface-7.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25e6a61dcb184453bb00eafa733169ab6d903e46f5c2ace4ad275386f9ab327a", size = 259806, upload-time = "2024-11-28T08:48:30.78Z" }, + { url = "https://files.pythonhosted.org/packages/a7/2c/82028f121d27c7e68632347fe04f4a6e0466e77bb36e104c8b074f3d7d7b/zope.interface-7.2-cp311-cp311-win_amd64.whl", hash = "sha256:3f6771d1647b1fc543d37640b45c06b34832a943c80d1db214a37c31161a93f1", size = 212305, upload-time = "2024-11-28T08:49:14.525Z" }, + { url = "https://files.pythonhosted.org/packages/68/0b/c7516bc3bad144c2496f355e35bd699443b82e9437aa02d9867653203b4a/zope.interface-7.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:086ee2f51eaef1e4a52bd7d3111a0404081dadae87f84c0ad4ce2649d4f708b7", size = 208959, upload-time = "2024-11-28T08:47:47.788Z" }, + { url = "https://files.pythonhosted.org/packages/a2/e9/1463036df1f78ff8c45a02642a7bf6931ae4a38a4acd6a8e07c128e387a7/zope.interface-7.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:21328fcc9d5b80768bf051faa35ab98fb979080c18e6f84ab3f27ce703bce465", size = 209357, upload-time = "2024-11-28T08:47:50.897Z" }, + { url = "https://files.pythonhosted.org/packages/07/a8/106ca4c2add440728e382f1b16c7d886563602487bdd90004788d45eb310/zope.interface-7.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6dd02ec01f4468da0f234da9d9c8545c5412fef80bc590cc51d8dd084138a89", size = 264235, upload-time = "2024-11-28T09:18:15.56Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ca/57286866285f4b8a4634c12ca1957c24bdac06eae28fd4a3a578e30cf906/zope.interface-7.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e7da17f53e25d1a3bde5da4601e026adc9e8071f9f6f936d0fe3fe84ace6d54", size = 259253, upload-time = "2024-11-28T08:48:29.025Z" }, + { url = "https://files.pythonhosted.org/packages/96/08/2103587ebc989b455cf05e858e7fbdfeedfc3373358320e9c513428290b1/zope.interface-7.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cab15ff4832580aa440dc9790b8a6128abd0b88b7ee4dd56abacbc52f212209d", size = 264702, upload-time = "2024-11-28T08:48:37.363Z" }, + { url = "https://files.pythonhosted.org/packages/5f/c7/3c67562e03b3752ba4ab6b23355f15a58ac2d023a6ef763caaca430f91f2/zope.interface-7.2-cp312-cp312-win_amd64.whl", hash = "sha256:29caad142a2355ce7cfea48725aa8bcf0067e2b5cc63fcf5cd9f97ad12d6afb5", size = 212466, upload-time = "2024-11-28T08:49:14.397Z" }, + { url = "https://files.pythonhosted.org/packages/c6/3b/e309d731712c1a1866d61b5356a069dd44e5b01e394b6cb49848fa2efbff/zope.interface-7.2-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:3e0350b51e88658d5ad126c6a57502b19d5f559f6cb0a628e3dc90442b53dd98", size = 208961, upload-time = "2024-11-28T08:48:29.865Z" }, + { url = "https://files.pythonhosted.org/packages/49/65/78e7cebca6be07c8fc4032bfbb123e500d60efdf7b86727bb8a071992108/zope.interface-7.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15398c000c094b8855d7d74f4fdc9e73aa02d4d0d5c775acdef98cdb1119768d", size = 209356, upload-time = "2024-11-28T08:48:33.297Z" }, + { url = "https://files.pythonhosted.org/packages/11/b1/627384b745310d082d29e3695db5f5a9188186676912c14b61a78bbc6afe/zope.interface-7.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:802176a9f99bd8cc276dcd3b8512808716492f6f557c11196d42e26c01a69a4c", size = 264196, upload-time = "2024-11-28T09:18:17.584Z" }, + { url = "https://files.pythonhosted.org/packages/b8/f6/54548df6dc73e30ac6c8a7ff1da73ac9007ba38f866397091d5a82237bd3/zope.interface-7.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb23f58a446a7f09db85eda09521a498e109f137b85fb278edb2e34841055398", size = 259237, upload-time = "2024-11-28T08:48:31.71Z" }, + { url = "https://files.pythonhosted.org/packages/b6/66/ac05b741c2129fdf668b85631d2268421c5cd1a9ff99be1674371139d665/zope.interface-7.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a71a5b541078d0ebe373a81a3b7e71432c61d12e660f1d67896ca62d9628045b", size = 264696, upload-time = "2024-11-28T08:48:41.161Z" }, + { url = "https://files.pythonhosted.org/packages/0a/2f/1bccc6f4cc882662162a1158cda1a7f616add2ffe322b28c99cb031b4ffc/zope.interface-7.2-cp313-cp313-win_amd64.whl", hash = "sha256:4893395d5dd2ba655c38ceb13014fd65667740f09fa5bb01caa1e6284e48c0cd", size = 212472, upload-time = "2024-11-28T08:49:56.587Z" }, +]