pax_global_header00006660000000000000000000000064147444116520014522gustar00rootroot0000000000000052 comment=e4c64a59c57b14e235dc5fd413044a0a3e4d9599 frenck-python-peblar-e4c64a5/000077500000000000000000000000001474441165200161715ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/.devcontainer/000077500000000000000000000000001474441165200207305ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/.devcontainer/devcontainer.json000066400000000000000000000037341474441165200243130ustar00rootroot00000000000000{ "customizations": { "codespaces": { "openFiles": ["README.md", "src/peblar/peblar.py", "src/peblar/models.py"] }, "vscode": { "extensions": [ "ms-python.python", "redhat.vscode-yaml", "esbenp.prettier-vscode", "GitHub.vscode-pull-request-github", "charliermarsh.ruff", "GitHub.vscode-github-actions", "ryanluker.vscode-coverage-gutters" ], "settings": { "[python]": { "editor.codeActionsOnSave": { "source.fixAll": true, "source.organizeImports": true } }, "coverage-gutters.customizable.context-menu": true, "coverage-gutters.customizable.status-bar-toggler-watchCoverageAndVisibleEditors-enabled": true, "coverage-gutters.showGutterCoverage": false, "coverage-gutters.showLineCoverage": true, "coverage-gutters.xmlname": "coverage.xml", "python.analysis.extraPaths": ["${workspaceFolder}/src"], "python.defaultInterpreterPath": ".venv/bin/python", "python.formatting.provider": "ruff", "python.linting.enabled": true, "python.linting.mypyEnabled": true, "python.linting.pylintEnabled": true, "python.testing.cwd": "${workspaceFolder}", "python.testing.pytestArgs": ["--cov-report=xml"], "python.testing.pytestEnabled": true, "ruff.importStrategy": "fromEnvironment", "ruff.interpreter": [".venv/bin/python"], "terminal.integrated.defaultProfile.linux": "zsh" } } }, "features": { "ghcr.io/devcontainers/features/github-cli:1": {}, "ghcr.io/devcontainers/features/node:1": {}, "ghcr.io/va-h/devcontainers-features/uv:1": {} }, "image": "mcr.microsoft.com/devcontainers/python:3.13", "name": "Asynchronous Python client for Peblar EV chargers", "updateContentCommand": ". ${NVM_DIR}/nvm.sh && nvm install && nvm use && npm install && uv sync --extra cli && uv run pre-commit install" } frenck-python-peblar-e4c64a5/.editorconfig000066400000000000000000000002741474441165200206510ustar00rootroot00000000000000root = true [*] charset = utf-8 end_of_line = lf indent_style = space insert_final_newline = true trim_trailing_whitespace = true indent_size = 2 [*.md] trim_trailing_whitespace = false frenck-python-peblar-e4c64a5/.gitattributes000066400000000000000000000000511474441165200210600ustar00rootroot00000000000000* text eol=lf *.py whitespace=error frenck-python-peblar-e4c64a5/.github/000077500000000000000000000000001474441165200175315ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/.github/CODEOWNERS000066400000000000000000000000221474441165200211160ustar00rootroot00000000000000.github/* @frenck frenck-python-peblar-e4c64a5/.github/CODE_OF_CONDUCT.md000066400000000000000000000062141474441165200223330ustar00rootroot00000000000000# Code of conduct ## Our pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our standards Examples of behavior that contributes to creating a positive environment include: - Using welcoming and inclusive language - Being respectful of differing viewpoints and experiences - Gracefully accepting constructive criticism - Focusing on what is best for the community - Showing empathy towards other community members Examples of unacceptable behavior by participants include: - The use of sexualized language or imagery and unwelcome sexual attention or advances - Trolling, insulting/derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or electronic address, without explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting ## Our responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project lead at frenck@addons.community. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project lead is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ frenck-python-peblar-e4c64a5/.github/CONTRIBUTING.md000066400000000000000000000022111474441165200217560ustar00rootroot00000000000000# Contributing When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. Please note we have a code of conduct, please follow it in all your interactions with the project. ## Issues and feature requests You've found a bug in the source code, a mistake in the documentation or maybe you'd like a new feature? You can help us by submitting an issue to our [GitHub Repository][github]. Before you create an issue, make sure you search the archive, maybe your question was already answered. Even better: You could submit a pull request with a fix / new feature! ## Pull request process 1. Search our repository for open or closed [pull requests][prs] that relates to your submission. You don't want to duplicate effort. 1. You may merge the pull request in once you have the sign-off of two other developers, or if you do not have permission to do that, you may request the second reviewer to merge it for you. [github]: https://github.com/frenck/python-peblar/issues [prs]: https://github.com/frenck/python-peblar/pulls frenck-python-peblar-e4c64a5/.github/FUNDING.yml000066400000000000000000000001061474441165200213430ustar00rootroot00000000000000--- github: frenck patreon: frenck custom: https://frenck.dev/donate/ frenck-python-peblar-e4c64a5/.github/ISSUE_TEMPLATE.md000066400000000000000000000005141474441165200222360ustar00rootroot00000000000000# Problem/Motivation > (Why the issue was filed) ## Expected behavior > (What you expected to happen) ## Actual behavior > (What actually happened) ## Steps to reproduce > (How can someone else make/see it happen) ## Proposed changes > (If you have a proposed change, workaround or fix, > describe the rationale behind it) frenck-python-peblar-e4c64a5/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000003761474441165200233400ustar00rootroot00000000000000# Proposed Changes > (Describe the changes and rationale behind them) ## Related Issues > ([Github link][autolink-references] to related issues or pull requests) [autolink-references]: https://help.github.com/articles/autolinked-references-and-urls/ frenck-python-peblar-e4c64a5/.github/labels.yml000066400000000000000000000054331474441165200215230ustar00rootroot00000000000000--- - name: "breaking-change" color: ee0701 description: "A breaking change for existing users." - name: "bugfix" color: ee0701 description: "Inconsistencies or issues which will cause a problem for users or implementers." - name: "documentation" color: 0052cc description: "Solely about the documentation of the project." - name: "enhancement" color: 1d76db description: "Enhancement of the code, not introducing new features." - name: "refactor" color: 1d76db description: "Improvement of existing code, not introducing new features." - name: "performance" color: 1d76db description: "Improving performance, not introducing new features." - name: "new-feature" color: 0e8a16 description: "New features or options." - name: "maintenance" color: 2af79e description: "Generic maintenance tasks." - name: "ci" color: 1d76db description: "Work that improves the continue integration." - name: "dependencies" color: 1d76db description: "Upgrade or downgrade of project dependencies." - name: "in-progress" color: fbca04 description: "Issue is currently being resolved by a developer." - name: "stale" color: fef2c0 description: "There has not been activity on this issue or PR for quite some time." - name: "no-stale" color: fef2c0 description: "This issue or PR is exempted from the stable bot." - name: "security" color: ee0701 description: "Marks a security issue that needs to be resolved asap." - name: "incomplete" color: fef2c0 description: "Marks a PR or issue that is missing information." - name: "invalid" color: fef2c0 description: "Marks a PR or issue that is missing information." - name: "beginner-friendly" color: 0e8a16 description: "Good first issue for people wanting to contribute to the project." - name: "help-wanted" color: 0e8a16 description: "We need some extra helping hands or expertise in order to resolve this." - name: "hacktoberfest" description: "Issues/PRs are participating in the Hacktoberfest." color: fbca04 - name: "hacktoberfest-accepted" description: "Issues/PRs are participating in the Hacktoberfest." color: fbca04 - name: "priority-critical" color: ee0701 description: "This should be dealt with ASAP. Not fixing this issue would be a serious error." - name: "priority-high" color: b60205 description: "After critical issues are fixed, these should be dealt with before any further issues." - name: "priority-medium" color: 0e8a16 description: "This issue may be useful, and needs some attention." - name: "priority-low" color: e4ea8a description: "Nice addition, maybe... someday..." - name: "major" color: b60205 description: "This PR causes a major version bump in the version number." - name: "minor" color: 0e8a16 description: "This PR causes a minor version bump in the version number." frenck-python-peblar-e4c64a5/.github/release-drafter.yml000066400000000000000000000020471474441165200233240ustar00rootroot00000000000000--- name-template: "v$RESOLVED_VERSION" tag-template: "v$RESOLVED_VERSION" change-template: "- $TITLE @$AUTHOR (#$NUMBER)" sort-direction: ascending categories: - title: "๐Ÿšจ Breaking changes" labels: - "breaking-change" - title: "โœจ New features" labels: - "new-feature" - title: "๐Ÿ› Bug fixes" labels: - "bugfix" - title: "๐Ÿš€ Enhancements" labels: - "enhancement" - "refactor" - "performance" - title: "๐Ÿงฐ Maintenance" labels: - "maintenance" - "ci" - title: "๐Ÿ“š Documentation" labels: - "documentation" - title: "โฌ†๏ธ Dependency updates" labels: - "dependencies" version-resolver: major: labels: - "major" - "breaking-change" minor: labels: - "minor" - "new-feature" patch: labels: - "bugfix" - "chore" - "ci" - "dependencies" - "documentation" - "enhancement" - "performance" - "refactor" default: patch template: | ## Whatโ€™s changed $CHANGES frenck-python-peblar-e4c64a5/.github/renovate.json000066400000000000000000000021231474441165200222450ustar00rootroot00000000000000{ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "rebaseWhen": "behind-base-branch", "dependencyDashboard": true, "labels": ["dependencies", "no-stale"], "lockFileMaintenance": { "enabled": true, "automerge": true }, "commitMessagePrefix": "โฌ†๏ธ", "packageRules": [ { "matchManagers": ["pep621"], "addLabels": ["python"] }, { "matchManagers": ["pep621"], "matchDepTypes": ["dev"], "rangeStrategy": "pin" }, { "matchManagers": ["pep621"], "matchUpdateTypes": ["minor", "patch"], "automerge": true }, { "matchManagers": ["npm", "nvm"], "addLabels": ["javascript"], "rangeStrategy": "pin" }, { "matchManagers": ["npm", "nvm"], "matchUpdateTypes": ["minor", "patch"], "automerge": true }, { "matchManagers": ["github-actions"], "addLabels": ["github_actions"], "rangeStrategy": "pin" }, { "matchManagers": ["github-actions"], "matchUpdateTypes": ["minor", "patch"], "automerge": true } ] } frenck-python-peblar-e4c64a5/.github/workflows/000077500000000000000000000000001474441165200215665ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/.github/workflows/labels.yaml000066400000000000000000000010121474441165200237060ustar00rootroot00000000000000--- name: Sync labels # yamllint disable-line rule:truthy on: push: branches: - main paths: - .github/labels.yml workflow_dispatch: jobs: labels: name: โ™ป๏ธ Sync labels runs-on: ubuntu-latest permissions: pull-requests: write steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 - name: ๐Ÿš€ Run Label Syncer uses: micnncim/action-label-syncer@v1.3.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} frenck-python-peblar-e4c64a5/.github/workflows/linting.yaml000066400000000000000000000110471474441165200241210ustar00rootroot00000000000000--- name: Linting # yamllint disable-line rule:truthy on: push: pull_request: workflow_dispatch: env: DEFAULT_PYTHON: "3.11" jobs: codespell: name: codespell runs-on: ubuntu-latest steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 - name: ๐Ÿ— Set up uv uses: astral-sh/setup-uv@v5.2.1 with: enable-cache: true python-version: ${{ env.DEFAULT_PYTHON }} - name: ๐Ÿ— Install dependencies run: uv sync --frozen --dev - name: ๐Ÿš€ Check code for common misspellings run: uv run pre-commit run codespell --all-files ruff: name: Ruff runs-on: ubuntu-latest steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 - name: ๐Ÿ— Set up uv uses: astral-sh/setup-uv@v5.2.1 with: enable-cache: true python-version: ${{ env.DEFAULT_PYTHON }} - name: ๐Ÿ— Install dependencies run: uv sync --extra cli --frozen --dev - name: ๐Ÿš€ Run ruff linter run: uv run ruff check --output-format=github . - name: ๐Ÿš€ Run ruff formatter run: uv run ruff format --check . pre-commit-hooks: name: pre-commit-hooks runs-on: ubuntu-latest steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 - name: ๐Ÿ— Set up uv uses: astral-sh/setup-uv@v5.2.1 with: enable-cache: true python-version: ${{ env.DEFAULT_PYTHON }} - name: ๐Ÿ— Install dependencies run: uv sync --frozen --dev - name: ๐Ÿš€ Check Python AST run: uv run pre-commit run check-ast --all-files - name: ๐Ÿš€ Check for case conflicts run: uv run pre-commit run check-case-conflict --all-files - name: ๐Ÿš€ Check docstring is first run: uv run pre-commit run check-docstring-first --all-files - name: ๐Ÿš€ Check that executables have shebangs run: uv run pre-commit run check-executables-have-shebangs --all-files - name: ๐Ÿš€ Check JSON files run: uv run pre-commit run check-json --all-files - name: ๐Ÿš€ Check for merge conflicts run: uv run pre-commit run check-merge-conflict --all-files - name: ๐Ÿš€ Check for broken symlinks run: uv run pre-commit run check-symlinks --all-files - name: ๐Ÿš€ Check TOML files run: uv run pre-commit run check-toml --all-files - name: ๐Ÿš€ Check XML files run: uv run pre-commit run check-xml --all-files - name: ๐Ÿš€ Check YAML files run: uv run pre-commit run check-yaml --all-files - name: ๐Ÿš€ Detect Private Keys run: uv run pre-commit run detect-private-key --all-files - name: ๐Ÿš€ Check End of Files run: uv run pre-commit run end-of-file-fixer --all-files - name: ๐Ÿš€ Trim Trailing Whitespace run: uv run pre-commit run trailing-whitespace --all-files pylint: name: pylint runs-on: ubuntu-latest steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 - name: ๐Ÿ— Set up uv uses: astral-sh/setup-uv@v5.2.1 with: enable-cache: true python-version: ${{ env.DEFAULT_PYTHON }} - name: ๐Ÿ— Install dependencies run: uv sync --extra cli --frozen --dev - name: ๐Ÿš€ Run pylint run: uv run pre-commit run pylint --all-files yamllint: name: yamllint runs-on: ubuntu-latest steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 - name: ๐Ÿ— Set up uv uses: astral-sh/setup-uv@v5.2.1 with: enable-cache: true python-version: ${{ env.DEFAULT_PYTHON }} - name: ๐Ÿ— Install dependencies run: uv sync --frozen --dev - name: ๐Ÿš€ Run yamllint run: uv run yamllint . prettier: name: Prettier runs-on: ubuntu-latest steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 - name: ๐Ÿ— Set up uv uses: astral-sh/setup-uv@v5.2.1 with: enable-cache: true python-version: ${{ env.DEFAULT_PYTHON }} - name: ๐Ÿ— Install dependencies run: uv sync --frozen --dev - name: ๐Ÿ— Set up Node.js uses: actions/setup-node@v4.1.0 with: node-version-file: ".nvmrc" cache: "npm" - name: ๐Ÿ— Install NPM dependencies run: npm install - name: ๐Ÿš€ Run prettier run: uv run pre-commit run prettier --all-files frenck-python-peblar-e4c64a5/.github/workflows/lock.yaml000066400000000000000000000010161474441165200234000ustar00rootroot00000000000000--- name: Lock # yamllint disable-line rule:truthy on: schedule: - cron: "0 9 * * *" workflow_dispatch: jobs: lock: name: ๐Ÿ”’ Lock closed issues and PRs runs-on: ubuntu-latest permissions: issues: write pull-requests: write discussions: write steps: - uses: dessant/lock-threads@v5.0.1 with: github-token: ${{ github.token }} issue-inactive-days: "30" issue-lock-reason: "" pr-inactive-days: "1" pr-lock-reason: "" frenck-python-peblar-e4c64a5/.github/workflows/pr-labels.yaml000066400000000000000000000013021474441165200243270ustar00rootroot00000000000000--- name: PR Labels # yamllint disable-line rule:truthy on: pull_request_target: types: - opened - labeled - unlabeled - synchronize workflow_call: jobs: pr_labels: name: Verify runs-on: ubuntu-latest steps: - name: ๐Ÿท Verify PR has a valid label uses: jesusvasquez333/verify-pr-label-action@v1.4.0 with: pull-request-number: "${{ github.event.pull_request.number }}" github-token: "${{ secrets.GITHUB_TOKEN }}" valid-labels: >- breaking-change, bugfix, documentation, enhancement, refactor, performance, new-feature, maintenance, ci, dependencies disable-reviews: true frenck-python-peblar-e4c64a5/.github/workflows/release-drafter.yaml000066400000000000000000000006761474441165200255300ustar00rootroot00000000000000--- name: Release Drafter # yamllint disable-line rule:truthy on: push: branches: - main workflow_dispatch: jobs: update_release_draft: name: โœ๏ธ Draft release runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - name: ๐Ÿš€ Run Release Drafter uses: release-drafter/release-drafter@v6.1.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} frenck-python-peblar-e4c64a5/.github/workflows/release.yaml000066400000000000000000000023571474441165200241010ustar00rootroot00000000000000--- name: Release # yamllint disable-line rule:truthy on: release: types: - published env: DEFAULT_PYTHON: "3.11" jobs: release: name: Releasing to PyPi runs-on: ubuntu-latest environment: name: release url: https://pypi.org/p/peblar permissions: contents: write id-token: write steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 - name: ๐Ÿ— Set up uv uses: astral-sh/setup-uv@v5.2.1 with: enable-cache: true python-version: ${{ env.DEFAULT_PYTHON }} - name: ๐Ÿ— Install dependencies run: uv sync --extra cli --frozen --dev - name: ๐Ÿ— Set package version run: | version="${{ github.event.release.tag_name }}" version="${version,,}" version="${version#v}" sed -i "s/^version = \".*\"/version = \"${version}\"/" pyproject.toml - name: ๐Ÿ— Build package run: uv build - name: ๐Ÿš€ Publish to PyPi run: uv publish - name: โœ๏ธ Sign published artifacts uses: sigstore/gh-action-sigstore-python@v3.0.0 with: inputs: ./dist/*.tar.gz ./dist/*.whl release-signing-artifacts: true frenck-python-peblar-e4c64a5/.github/workflows/stale.yaml000066400000000000000000000026601474441165200235660ustar00rootroot00000000000000--- name: Stale # yamllint disable-line rule:truthy on: schedule: - cron: "0 8 * * *" workflow_dispatch: jobs: stale: name: ๐Ÿงน Clean up stale issues and PRs runs-on: ubuntu-latest permissions: issues: write pull-requests: write steps: - name: ๐Ÿš€ Run stale uses: actions/stale@v9.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 30 days-before-close: 7 remove-stale-when-updated: true stale-issue-label: "stale" exempt-issue-labels: "no-stale,help-wanted" stale-issue-message: > There hasn't been any activity on this issue recently, so we clean up some of the older and inactive issues. Please make sure to update to the latest version and check if that solves the issue. Let us know if that works for you by leaving a comment ๐Ÿ‘ This issue has now been marked as stale and will be closed if no further activity occurs. Thanks! stale-pr-label: "stale" exempt-pr-labels: "no-stale" stale-pr-message: > There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. Thank you for your contributions. frenck-python-peblar-e4c64a5/.github/workflows/tests.yaml000066400000000000000000000033021474441165200236120ustar00rootroot00000000000000--- name: Testing # yamllint disable-line rule:truthy on: push: pull_request: workflow_dispatch: env: DEFAULT_PYTHON: "3.11" jobs: pytest: name: Python ${{ matrix.python }} runs-on: ubuntu-latest strategy: matrix: python: ["3.11", "3.12", "3.13"] steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 - name: ๐Ÿ— Set up uv uses: astral-sh/setup-uv@v5.2.1 with: enable-cache: true python-version: ${{ env.DEFAULT_PYTHON }} - name: ๐Ÿ— Install dependencies run: uv sync --extra cli --frozen --dev - name: ๐Ÿš€ Run pytest run: uv run pytest --cov peblar tests - name: โฌ†๏ธ Upload coverage artifact uses: actions/upload-artifact@v4.6.0 with: name: coverage-${{ matrix.python }} path: .coverage if-no-files-found: error include-hidden-files: true coverage: runs-on: ubuntu-latest needs: pytest steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 with: fetch-depth: 0 - name: โฌ‡๏ธ Download coverage data uses: actions/download-artifact@v4.1.8 - name: ๐Ÿ— Set up uv uses: astral-sh/setup-uv@v5.2.1 with: enable-cache: true python-version: ${{ env.DEFAULT_PYTHON }} - name: ๐Ÿ— Install dependencies run: uv sync --extra cli --frozen --dev - name: ๐Ÿš€ Process coverage results run: | uv run coverage combine coverage*/.coverage* uv run coverage xml -i - name: ๐Ÿš€ Upload coverage report uses: codecov/codecov-action@v5.2.0 frenck-python-peblar-e4c64a5/.github/workflows/typing.yaml000066400000000000000000000011441474441165200237640ustar00rootroot00000000000000--- name: Typing # yamllint disable-line rule:truthy on: push: pull_request: workflow_dispatch: env: DEFAULT_PYTHON: "3.11" jobs: mypy: name: mypy runs-on: ubuntu-latest steps: - name: โคต๏ธ Check out code from GitHub uses: actions/checkout@v4.2.2 - name: ๐Ÿ— Set up uv uses: astral-sh/setup-uv@v5.2.1 with: enable-cache: true python-version: ${{ env.DEFAULT_PYTHON }} - name: ๐Ÿ— Install dependencies run: uv sync --extra cli --frozen --dev - name: ๐Ÿš€ Run mypy run: uv run mypy examples src tests frenck-python-peblar-e4c64a5/.gitignore000066400000000000000000000027011474441165200201610ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # OSX useful to ignore *.DS_Store .AppleDouble .LSOverride # Thumbnails ._* # Files that might appear in the root of a volume .DocumentRevisions-V100 .fseventsd .Spotlight-V100 .TemporaryItems .Trashes .VolumeIcon.icns .com.apple.timemachine.donotpresent # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *,cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log # Sphinx documentation docs/_build/ # pyenv .python-version # virtualenv .venv venv/ ENV/ # mypy .mypy_cache/ # ruff .ruff_cache # Visual Studio Code .vscode # IntelliJ Idea family of suites .idea *.iml ## File-based project format: *.ipr *.iws ## mpeltonen/sbt-idea plugin .idea_modules/ # PyBuilder target/ # Cookiecutter output/ python_boilerplate/ # Node node_modules/ # Deepcode AI .dccache frenck-python-peblar-e4c64a5/.nvmrc000066400000000000000000000000101474441165200173060ustar00rootroot0000000000000022.13.1 frenck-python-peblar-e4c64a5/.pre-commit-config.yaml000066400000000000000000000075351474441165200224640ustar00rootroot00000000000000--- repos: - repo: local hooks: - id: ruff-check name: ๐Ÿถ Ruff Linter language: system types: [python] entry: uv run ruff check --fix require_serial: true stages: [pre-commit, pre-push, manual] - id: ruff-format name: ๐Ÿถ Ruff Formatter language: system types: [python] entry: uv run ruff format require_serial: true stages: [pre-commit, pre-push, manual] - id: check-ast name: ๐Ÿ Check Python AST language: system types: [python] entry: uv run check-ast - id: check-case-conflict name: ๐Ÿ”  Check for case conflicts language: system entry: uv run check-case-conflict - id: check-docstring-first name: โ„น๏ธ Check docstring is first language: system types: [python] entry: uv run check-docstring-first - id: check-executables-have-shebangs name: ๐Ÿง Check that executables have shebangs language: system types: [text, executable] entry: uv run check-executables-have-shebangs stages: [pre-commit, pre-push, manual] - id: check-json name: ๏ฝ› Check JSON files language: system types: [json] entry: uv run check-json - id: check-merge-conflict name: ๐Ÿ’ฅ Check for merge conflicts language: system types: [text] entry: uv run check-merge-conflict - id: check-symlinks name: ๐Ÿ”— Check for broken symlinks language: system types: [symlink] entry: uv run check-symlinks - id: check-toml name: โœ… Check TOML files language: system types: [toml] entry: uv run check-toml - id: check-xml name: โœ… Check XML files entry: check-xml language: system types: [xml] - id: check-yaml name: โœ… Check YAML files language: system types: [yaml] entry: uv run check-yaml - id: codespell name: โœ… Check code for common misspellings language: system types: [text] exclude: ^uv\.lock$ entry: uv run codespell - id: detect-private-key name: ๐Ÿ•ต๏ธ Detect Private Keys language: system types: [text] entry: uv run detect-private-key - id: end-of-file-fixer name: โฎ Fix End of Files language: system types: [text] entry: uv run end-of-file-fixer stages: [pre-commit, pre-push, manual] - id: mypy name: ๐Ÿ†Ž Static type checking using mypy language: system types: [python] entry: uv run mypy require_serial: true - id: no-commit-to-branch name: ๐Ÿ›‘ Don't commit to main branchpre-commit migrate-config language: system entry: uv run no-commit-to-branch pass_filenames: false always_run: true args: - --branch=main - id: prettier name: ๐Ÿ’„ Ensuring files are prettier language: system types: [yaml, json, markdown] entry: npm run prettier pass_filenames: false - id: pylint name: ๐ŸŒŸ Starring code with pylint language: system types: [python] entry: uv run pylint - id: pytest name: ๐Ÿงช Running tests and test coverage with pytest language: system types: [python] entry: uv run pytest pass_filenames: false - id: trailing-whitespace name: โœ„ Trim Trailing Whitespace language: system types: [text] entry: uv run trailing-whitespace-fixer stages: [pre-commit, pre-push, manual] - id: yamllint name: ๐ŸŽ— Check YAML files with yamllint language: system types: [yaml] entry: uv run yamllint frenck-python-peblar-e4c64a5/.prettierignore000066400000000000000000000027011474441165200212340ustar00rootroot00000000000000# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # OSX useful to ignore *.DS_Store .AppleDouble .LSOverride # Thumbnails ._* # Files that might appear in the root of a volume .DocumentRevisions-V100 .fseventsd .Spotlight-V100 .TemporaryItems .Trashes .VolumeIcon.icns .com.apple.timemachine.donotpresent # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *,cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log # Sphinx documentation docs/_build/ # pyenv .python-version # virtualenv .venv venv/ ENV/ # mypy .mypy_cache/ # ruff .ruff_cache # Visual Studio Code .vscode # IntelliJ Idea family of suites .idea *.iml ## File-based project format: *.ipr *.iws ## mpeltonen/sbt-idea plugin .idea_modules/ # PyBuilder target/ # Cookiecutter output/ python_boilerplate/ # Node node_modules/ # Deepcode AI .dccache frenck-python-peblar-e4c64a5/.yamllint000066400000000000000000000024001474441165200200170ustar00rootroot00000000000000--- ignore: - .venv rules: braces: level: error min-spaces-inside: 0 max-spaces-inside: 1 min-spaces-inside-empty: -1 max-spaces-inside-empty: -1 brackets: level: error min-spaces-inside: 0 max-spaces-inside: 0 min-spaces-inside-empty: -1 max-spaces-inside-empty: -1 colons: level: error max-spaces-before: 0 max-spaces-after: 1 commas: level: error max-spaces-before: 0 min-spaces-after: 1 max-spaces-after: 1 comments: level: error require-starting-space: true min-spaces-from-content: 1 comments-indentation: level: error document-end: level: error present: false document-start: level: error present: true empty-lines: level: error max: 1 max-start: 0 max-end: 1 hyphens: level: error max-spaces-after: 1 indentation: level: error spaces: 2 indent-sequences: true check-multi-line-strings: false key-duplicates: level: error line-length: level: warning max: 120 allow-non-breakable-words: true allow-non-breakable-inline-mappings: true new-line-at-end-of-file: level: error new-lines: level: error type: unix trailing-spaces: level: error truthy: level: error frenck-python-peblar-e4c64a5/LICENSE.md000066400000000000000000000020651474441165200176000ustar00rootroot00000000000000# MIT License Copyright (c) 2023-2024 Franck Nijhof Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. frenck-python-peblar-e4c64a5/README.md000066400000000000000000000152051474441165200174530ustar00rootroot00000000000000# Python: Asynchronous Python client for Peblar EV chargers [![GitHub Release][releases-shield]][releases] [![Python Versions][python-versions-shield]][pypi] ![Project Stage][project-stage-shield] ![Project Maintenance][maintenance-shield] [![License][license-shield]](LICENSE.md) [![Build Status][build-shield]][build] [![Code Coverage][codecov-shield]][codecov] [![Open in Dev Containers][devcontainer-shield]][devcontainer] [![Sponsor Frenck via GitHub Sponsors][github-sponsors-shield]][github-sponsors] [![Support Frenck on Patreon][patreon-shield]][patreon] Asynchronous Python client for Peblar's Rocksolid EV chargers ## About This package allows you to control and monitor [Peblar EV Chargers](https://peblar.com) programmatically. It is mainly created to allow third-party programs to automate the behavior of a Peblar charger. Additionally, this package contains a CLI tool, which can be used standalone, proving a command-line interface to control and monitor Peblar chargers. Known compatible and tested Peblar chargers: - Peblar Home ## Installation ```bash pip install peblar ``` In case you want to use the CLI tools, install the package with the following extra: ```bash pip install peblar[cli] ``` ## CLI usage The Peblar CLI tool provided in this library provides all the functionalities this library provides but from the command line. The CLI comes with built-in help, which can be accessed by using the `--help` ```bash peblar --help ``` To scan for Peblar chargers on your network: ```bash peblar scan ``` For more details, access the built-in help of the CLI using the `--help` flag. ## Python usage Using this library in Python: ```python import asyncio from peblar import Peblar async def main() -> None: """Show example of programmatically control a Peblar charger.""" async with Peblar(host="192.168.1.123") as peblar: await peblar.login(password="Sup3rS3cr3t!") await peblar.identify() system_information = await peblar.system_information() print(system_information) if __name__ == "__main__": asyncio.run(main()) ``` ## Changelog & releases This repository keeps a change log using [GitHub's releases][releases] functionality. The format of the log is based on [Keep a Changelog][keepchangelog]. Releases are based on [Semantic Versioning][semver], and use the format of `MAJOR.MINOR.PATCH`. In a nutshell, the version will be incremented based on the following: - `MAJOR`: Incompatible or major changes. - `MINOR`: Backwards-compatible new features and enhancements. - `PATCH`: Backwards-compatible bugfixes and package updates. ## Contributing This is an active open-source project. We are always open to people who want to use the code or contribute to it. We've set up a separate document for our [contribution guidelines](CONTRIBUTING.md). Thank you for being involved! :heart_eyes: ## Setting up a development environment The easiest way to start is by opening a CodeSpace here on GitHub, or by using the [Dev Container][devcontainer] feature of Visual Studio Code. [![Open in Dev Containers][devcontainer-shield]][devcontainer] This Python project is fully managed using the [uv] dependency manager. But also relies on the use of NodeJS for certain checks during development. You need at least: - Python 3.11+ - [uv][uv-install] - NodeJS 20+ (including NPM) To install all packages, including all development requirements: ```bash npm install uv sync --extra cli ``` As this repository uses the [pre-commit][pre-commit] framework, all changes are linted and tested with each commit. You can run all checks and tests manually, using the following command: ```bash uv run pre-commit run --all-files ``` To run just the Python tests: ```bash uv run pytest ``` ## Authors & contributors The original setup of this repository is by [Franck Nijhof][frenck]. For a full list of all authors and contributors, check [the contributor's page][contributors]. ## License MIT License Copyright (c) 2024 Franck Nijhof Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. [build-shield]: https://github.com/frenck/python-peblar/actions/workflows/tests.yaml/badge.svg [build]: https://github.com/frenck/python-peblar/actions/workflows/tests.yaml [codecov-shield]: https://codecov.io/gh/frenck/python-peblar/branch/master/graph/badge.svg [codecov]: https://codecov.io/gh/frenck/python-peblar [contributors]: https://github.com/frenck/python-peblar/graphs/contributors [devcontainer-shield]: https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode [devcontainer]: https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/frenck/python-peblar [frenck]: https://github.com/frenck [github-sponsors-shield]: https://frenck.dev/wp-content/uploads/2019/12/github_sponsor.png [github-sponsors]: https://github.com/sponsors/frenck [keepchangelog]: http://keepachangelog.com/en/1.0.0/ [license-shield]: https://img.shields.io/github/license/frenck/python-peblar.svg [maintenance-shield]: https://img.shields.io/maintenance/yes/2023-2024.svg [patreon-shield]: https://frenck.dev/wp-content/uploads/2019/12/patreon.png [patreon]: https://www.patreon.com/frenck [uv-install]: https://docs.astral.sh/uv/getting-started/installation/ [uv]: https://docs.astral.sh/uv/ [pre-commit]: https://pre-commit.com/ [project-stage-shield]: https://img.shields.io/badge/project%20stage-production%20ready-brightgreen.svg [pypi]: https://pypi.org/project/peblar/ [python-versions-shield]: https://img.shields.io/pypi/pyversions/peblar [releases-shield]: https://img.shields.io/github/release/frenck/python-peblar.svg [releases]: https://github.com/frenck/python-peblar/releases [semver]: http://semver.org/spec/v2.0.0.html frenck-python-peblar-e4c64a5/examples/000077500000000000000000000000001474441165200200075ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/examples/__init__.py000066400000000000000000000000411474441165200221130ustar00rootroot00000000000000"""Examples for this library.""" frenck-python-peblar-e4c64a5/examples/example.py000066400000000000000000000010001474441165200220030ustar00rootroot00000000000000# pylint: disable=W0621 """Asynchronous Python client for Peblar EV chargers.""" import asyncio from peblar import Peblar async def main() -> None: """Show example of programmatically control a Peblar charger.""" async with Peblar(host="192.168.1.123") as peblar: await peblar.login(password="Sup3rS3cr3t!") await peblar.identify() system_information = await peblar.system_information() print(system_information) if __name__ == "__main__": asyncio.run(main()) frenck-python-peblar-e4c64a5/examples/ruff.toml000066400000000000000000000003341474441165200216460ustar00rootroot00000000000000# This extend our general Ruff rules specifically for the examples extend = "../pyproject.toml" lint.extend-ignore = [ "T201", # Allow the use of print() in examples "S106", # We have an demo token in the example ] frenck-python-peblar-e4c64a5/package-lock.json000066400000000000000000000014031474441165200214030ustar00rootroot00000000000000{ "name": "peblar", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "peblar", "version": "0.0.0", "license": "MIT", "devDependencies": { "prettier": "3.4.2" } }, "node_modules/prettier": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", "dev": true, "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, "engines": { "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } } } } frenck-python-peblar-e4c64a5/package.json000066400000000000000000000005251474441165200204610ustar00rootroot00000000000000{ "name": "peblar", "version": "0.0.0", "private": true, "description": "Asynchronous Python client for Peblar EV chargers", "scripts": { "prettier": "prettier --write **/*.{json,js,md,yml,yaml}" }, "author": "Franck Nijhof ", "license": "MIT", "devDependencies": { "prettier": "3.4.2" } } frenck-python-peblar-e4c64a5/pyproject.toml000066400000000000000000000074611474441165200211150ustar00rootroot00000000000000[project] name = "peblar" version = "0.0.0" license = { text = "MIT License" } description = "Asynchronous Python client for Peblar EV chargers." authors = [{ name = "Franck Nijhof", email = "opensource@frenck.dev"}] maintainers = [{ name = "Franck Nijhof", email = "opensource@frenck.dev"}] readme = "README.md" classifiers = [ "Development Status :: 3 - Alpha", "Framework :: AsyncIO", "Intended Audience :: Developers", "Natural Language :: English", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules", ] keywords = [ "bluebuilt", "charger", "chargers", "ev", "hybrid", "ocpp", "peblar", ] requires-python = ">=3.11" dependencies = [ "aiohttp>=3.0.0", "awesomeversion>=22.8.0", "backoff>=2.2.1", "mashumaro>=3.10", "orjson>=3.9.8", "yarl>=1.6.0", ] [project.optional-dependencies] cli = [ "typer>=0.15.1", "zeroconf>=0.126.0", ] [project.scripts] peblar = "peblar.cli:cli" [project.urls] Changelog = "https://github.com/frenck/python-peblar/releases" Issues = "https://github.com/frenck/python-peblar/issues" Repository = "https://github.com/frenck/python-peblar" [tool.coverage.run] plugins = ["covdefaults"] source = ["peblar"] [tool.coverage.report] show_missing = true fail_under = 50 omit = ["src/peblar/cli/*"] [tool.mypy] # Specify the target platform details in config, so your developers are # free to run mypy on Windows, Linux, or macOS and get consistent # results. platform = "linux" python_version = "3.11" # show error messages from unrelated files follow_imports = "normal" # suppress errors about unsatisfied imports ignore_missing_imports = true # be strict check_untyped_defs = true disallow_any_generics = true disallow_incomplete_defs = true disallow_subclassing_any = true disallow_untyped_calls = true disallow_untyped_decorators = true disallow_untyped_defs = true no_implicit_optional = true no_implicit_reexport = true strict_optional = true warn_incomplete_stub = true warn_no_return = true warn_redundant_casts = true warn_return_any = true warn_unused_configs = true warn_unused_ignores = true [tool.pylint.MASTER] extension-pkg-whitelist = [ "orjson", ] ignore = [ "tests", ] [tool.pylint.BASIC] good-names = [ "_", "ex", "fp", "i", "id", "j", "k", "on", "Run", "T", ] [tool.pylint.DESIGN] max-attributes = 8 [tool.pylint."MESSAGES CONTROL"] disable = [ "duplicate-code", "format", "unsubscriptable-object", ] [tool.pylint.SIMILARITIES] ignore-imports = true [tool.pylint.FORMAT] max-line-length = 88 [tool.pytest.ini_options] addopts = "--cov" asyncio_mode = "auto" [tool.ruff.lint] ignore = [ "ANN401", # Opinioated warning on disallowing dynamically typed expressions "D203", # Conflicts with other rules "D213", # Conflicts with other rules "D417", # False positives in some occasions "PLR2004", # Just annoying, not really useful # Conflicts with the Ruff formatter "COM812", "ISC001", ] select = ["ALL"] [tool.ruff.lint.flake8-pytest-style] fixture-parentheses = false mark-parentheses = false [tool.ruff.lint.isort] known-first-party = ["peblar"] [tool.ruff.lint.flake8-type-checking] runtime-evaluated-base-classes = ["mashumaro.mixins.orjson.DataClassORJSONMixin"] [tool.ruff.lint.mccabe] max-complexity = 25 [tool.uv] prerelease = "allow" dev-dependencies = [ "aresponses==3.0.0", "codespell==2.4.0", "covdefaults==2.3.0", "coverage[toml]==7.6.10", "mypy==1.14.1", "pre-commit==4.1.0", "pre-commit-hooks==5.0.0", "pylint==3.3.3", "pytest==8.3.4", "pytest-asyncio==0.25.2", "pytest-cov==6.0.0", "ruff==0.9.2", "syrupy==4.8.1", "yamllint==1.35.1", ] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" frenck-python-peblar-e4c64a5/sonar-project.properties000066400000000000000000000010771474441165200231020ustar00rootroot00000000000000sonar.organization=frenck sonar.projectKey=frenck_python-peblar sonar.projectName=Asynchronous Python client for Peblar EV chargers sonar.projectVersion=1.0 sonar.links.homepage=https://github.com/frenck/python-peblar sonar.links.ci=https://github.com/frenck/python-peblar/actions sonar.links.issue=https://github.com/frenck/python-peblar/issues sonar.links.scm=https://github.com/frenck/python-peblar/tree/main sonar.language=py sonar.sourceEncoding=UTF-8 sonar.sources=src sonar.tests=tests sonar.python.version=3.11, 3.12 sonar.python.coverage.reportPaths=coverage.xml frenck-python-peblar-e4c64a5/src/000077500000000000000000000000001474441165200167605ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/src/peblar/000077500000000000000000000000001474441165200202255ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/src/peblar/__init__.py000066400000000000000000000021111474441165200223310ustar00rootroot00000000000000"""Asynchronous Python client for Peblar EV chargers.""" from .const import ( AccessMode, ChargeLimiter, CPState, LedIntensityMode, SmartChargingMode, SolarChargingMode, SoundVolume, ) from .exceptions import ( PeblarAuthenticationError, PeblarConnectionError, PeblarConnectionTimeoutError, PeblarError, PeblarResponseError, ) from .models import ( PeblarEVInterface, PeblarHealth, PeblarMeter, PeblarSystem, PeblarSystemInformation, PeblarUserConfiguration, PeblarVersions, ) from .peblar import Peblar, PeblarApi __all__ = [ "AccessMode", "CPState", "ChargeLimiter", "LedIntensityMode", "Peblar", "PeblarApi", "PeblarAuthenticationError", "PeblarConnectionError", "PeblarConnectionTimeoutError", "PeblarEVInterface", "PeblarError", "PeblarHealth", "PeblarMeter", "PeblarResponseError", "PeblarSystem", "PeblarSystemInformation", "PeblarUserConfiguration", "PeblarVersions", "SmartChargingMode", "SolarChargingMode", "SoundVolume", ] frenck-python-peblar-e4c64a5/src/peblar/cli/000077500000000000000000000000001474441165200207745ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/src/peblar/cli/__init__.py000066400000000000000000001073661474441165200231220ustar00rootroot00000000000000"""Asynchronous Python client for Peblar EV chargers.""" import asyncio import sys from typing import Annotated import typer from rich.console import Console from rich.live import Live from rich.panel import Panel from rich.table import Table from zeroconf import ServiceStateChange, Zeroconf from zeroconf.asyncio import AsyncServiceBrowser, AsyncServiceInfo, AsyncZeroconf from peblar.const import AccessMode, CPState, PackageType, SmartChargingMode from peblar.exceptions import ( PeblarAuthenticationError, PeblarConnectionError, PeblarUnsupportedFirmwareVersionError, ) from peblar.peblar import Peblar from .async_typer import AsyncTyper cli = AsyncTyper(help="Peblar CLI", no_args_is_help=True, add_completion=False) console = Console() def convert_to_string(value: object) -> str: """Convert a value to a string.""" if isinstance(value, bool): return "โœ…" if value else "โŒ" if isinstance(value, dict): return "".join(f"{key}: {value}" for key, value in value.items()) return str(value) @cli.error_handler(PeblarAuthenticationError) def authentication_error_handler(_: PeblarAuthenticationError) -> None: """Handle authentication errors.""" message = """ The provided Peblar charger password is invalid. """ panel = Panel( message, expand=False, title="Authentication error", border_style="red bold", ) console.print(panel) sys.exit(1) # @cli.error_handler(PeblarConnectionError) def connection_error_handler(_: PeblarConnectionError) -> None: """Handle connection errors.""" message = """ Could not connect to the specified Peblar charger. Please make sure that the charger is powered on, connected to the network and that you have specified the correct IP address or hostname. If you are not sure what the IP address or hostname of your Peblar charger is, you can use the scan command to find it: peblar scan """ panel = Panel( message, expand=False, title="Connection error", border_style="red bold", ) console.print(panel) sys.exit(1) @cli.error_handler(PeblarUnsupportedFirmwareVersionError) def unsupported_firmware_version_error_handler( _: PeblarUnsupportedFirmwareVersionError, ) -> None: """Handle unsupported version errors.""" message = """ The specified Peblar charger is running an unsupported firmware version. The tooling currently only supports firmware versions XXX and higher. """ panel = Panel( message, expand=False, title="Unsupported firmware version", border_style="red bold", ) console.print(panel) sys.exit(1) @cli.command("versions") async def versions( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], ) -> None: """Get the software version information the Peblar charger.""" async with Peblar(host=host) as peblar: await peblar.login(password=password) current = await peblar.current_versions() available = await peblar.available_versions() table = Table(title="Peblar charger versions") table.add_column("Type", style="cyan bold") table.add_column("Installed version", style="cyan bold") table.add_column("Available version", style="cyan bold") firmware = "โœ…" if current.firmware == available.firmware else "โฌ†๏ธ" customization = "โœ…" if current.customization == available.customization else "โฌ†๏ธ" table.add_row( "Firmware", current.firmware, f"{firmware} {available.firmware}", ) table.add_row( "Customization", current.customization, f"{customization} {available.customization}", ) console.print(table) @cli.command("identify") async def identify( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], ) -> None: """Flash the LEDs on the Peblar charger to identify it.""" with console.status("[cyan]Identifying...", spinner="toggle12"): async with Peblar(host=host) as peblar: await peblar.login(password=password) await peblar.identify() console.print("โœ…[green]Success!") @cli.command("reboot") async def reboot( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], ) -> None: """Reboot the Peblar charger.""" with console.status("[cyan]Rebooting...", spinner="toggle12"): async with Peblar(host=host) as peblar: await peblar.login(password=password) await peblar.reboot() console.print("โœ…[green]Success!") @cli.command("update") async def update( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], firmware: Annotated[ bool, typer.Option( help="Update the firmware", ), ] = False, customization: Annotated[ bool, typer.Option( help="Update the customization", ), ] = False, ) -> None: """Update the Peblar charger.""" if not firmware and not customization: msg = "At least one of --firmware or --customization must be used." raise typer.BadParameter(msg) if firmware and customization: msg = "--firmware cannot be used with --customization." raise typer.BadParameter(msg) with console.status("[cyan]Updating...", spinner="toggle12"): async with Peblar(host=host) as peblar: await peblar.login(password=password) if firmware: await peblar.update(package_type=PackageType.FIRMWARE) if customization: await peblar.update(package_type=PackageType.CUSTOMIZATION) console.print("โœ…[green]Success!") @cli.command("api") # pylint: disable=too-many-arguments,too-many-positional-arguments async def rest_api( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], enable: Annotated[ bool, typer.Option( help="Enable the local REST API", ), ] = False, disable: Annotated[ bool, typer.Option( help="Disable the local REST API", ), ] = False, read: Annotated[ bool, typer.Option( help="Set access mode to read-only", ), ] = False, write: Annotated[ bool, typer.Option( help="Set access mode to read-only", ), ] = False, generate_new_token: Annotated[ bool, typer.Option( help="Generate a new API token", ), ] = False, ) -> None: """Control access to the Local REST API.""" if enable and disable: msg = "--disable cannot be used with --enable." raise typer.BadParameter(msg) if read and write: msg = "--read cannot be used with --write." raise typer.BadParameter(msg) async with Peblar(host=host) as peblar: await peblar.login(password=password) if enable or disable or read or write or generate_new_token: with console.status("[cyan]Adjusting...", spinner="toggle12"): if enable: await peblar.rest_api(enable=True) if disable: await peblar.rest_api(enable=False) if read: await peblar.rest_api(access_mode=AccessMode.READ_ONLY) if write: await peblar.rest_api(access_mode=AccessMode.READ_WRITE) if generate_new_token: await peblar.api_token(generate_new_api_token=generate_new_token) console.print("โœ…[green]Success!") config = await peblar.user_configuration() token = await peblar.api_token() table = Table(title="Peblar Local REST API configuration") table.add_column("Property", style="cyan bold") table.add_column("Value", style="bold") table.add_row( "Local REST API enabled", convert_to_string(config.local_rest_api_enabled) ) table.add_row("Local REST API access mode", config.local_rest_api_access_mode.value) table.add_row("Local REST API token", token) console.print(table) @cli.command("modbus") # pylint: disable=too-many-arguments,too-many-positional-arguments async def modbus( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], enable: Annotated[ bool, typer.Option( help="Enable the Modbus API", ), ] = False, disable: Annotated[ bool, typer.Option( help="Disable the Modbus API", ), ] = False, read: Annotated[ bool, typer.Option( help="Set access mode to read-only", ), ] = False, write: Annotated[ bool, typer.Option( help="Set access mode to read-only", ), ] = False, ) -> None: """Control access to the Modbus API.""" if enable and disable: msg = "--disable cannot be used with --enable." raise typer.BadParameter(msg) if read and write: msg = "--read cannot be used with --write." raise typer.BadParameter(msg) async with Peblar(host=host) as peblar: await peblar.login(password=password) if enable or disable or read or write: with console.status("[cyan]Adjusting...", spinner="toggle12"): if enable: await peblar.modbus_api(enable=True) if disable: await peblar.modbus_api(enable=False) if read: await peblar.modbus_api(access_mode=AccessMode.READ_ONLY) if write: await peblar.modbus_api(access_mode=AccessMode.READ_WRITE) console.print("โœ…[green]Success!") config = await peblar.user_configuration() table = Table(title="Peblar Modbus API configuration") table.add_column("Property", style="cyan bold") table.add_column("Value", style="bold") table.add_row("Modbus API enabled", convert_to_string(config.modbus_server_enabled)) table.add_row("Modbus API access mode", config.modbus_server_access_mode.value) console.print(table) @cli.command("info") async def system_information( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], ) -> None: """List information about the Peblar charger.""" async with Peblar(host=host) as peblar: await peblar.login(password=password) info = await peblar.system_information() table = Table(title="Peblar charger information") table.add_column("Property", style="cyan bold") table.add_column("Value", style="bold") table.add_row("Customer ID", info.customer_id) table.add_row("Ethernet MAC address", info.ethernet_mac_address) table.add_row("Firmware version", info.firmware_version) table.add_row( "Hardware fixed cable rating", f"{info.hardware_fixed_cable_rating}A", ) table.add_row("Hardware has BOP", convert_to_string(info.hardware_has_bop)) table.add_row("Hardware has buzzer", convert_to_string(info.hardware_has_buzzer)) table.add_row( "Hardware has Eichrecht laser marking", convert_to_string(info.hardware_has_eichrecht_laser_marking), ) table.add_row( "Hardware has Ethernet", convert_to_string(info.hardware_has_ethernet) ) table.add_row("Hardware has LED", convert_to_string(info.hardware_has_led)) table.add_row("Hardware has LTE", convert_to_string(info.hardware_has_lte)) table.add_row( "Hardware has meter display", convert_to_string(info.hardware_has_meter_display) ) table.add_row("Hardware has meter", convert_to_string(info.hardware_has_meter)) table.add_row("Hardware has PLC", convert_to_string(info.hardware_has_plc)) table.add_row("Hardware has RFID", convert_to_string(info.hardware_has_rfid)) table.add_row("Hardware has RS485", convert_to_string(info.hardware_has_rs485)) table.add_row("Hardware has socket", convert_to_string(info.hardware_has_socket)) table.add_row("Hardware has TPM", convert_to_string(info.hardware_has_tpm)) table.add_row("Hardware has WLAN", convert_to_string(info.hardware_has_wlan)) table.add_row("Hardware max current", f"{info.hardware_max_current}A") table.add_row( "Hardware one or three phase", convert_to_string(info.hardware_one_or_three_phase), ) table.add_row("Hostname", info.hostname) table.add_row("Mainboard part number", info.mainboard_part_number) table.add_row("Mainboard serial number", info.mainboard_serial_number) table.add_row("Meter firmware version", info.meter_firmware_version) table.add_row("Product model name", info.product_model_name) table.add_row("Product number", info.product_number) table.add_row("Product serial number", info.product_serial_number) table.add_row("Product vendor name", info.product_vendor_name) table.add_row("WLAN AP MAC address", info.wlan_ap_mac_address) table.add_row("WLAN MAC address", info.wlan_mac_address) console.print(table) @cli.command("config") async def user_configuration( # pylint: disable=too-many-statements host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], ) -> None: """List information about the user configuration.""" async with Peblar(host=host) as peblar: await peblar.login(password=password) config = await peblar.user_configuration() table = Table(title="Peblar user configuration") table.add_column("Property", style="cyan bold") table.add_column("Value", style="bold") table.add_row( "BOP fallback current", convert_to_string(config.bop_fallback_current) ) table.add_row("BOP HomeWizard address", config.bop_home_wizard_address) table.add_row( "BOP source parameters", convert_to_string(config.bop_source_parameters) ) table.add_row("BOP source", config.bop_source) table.add_row("Buzzer volume", convert_to_string(config.buzzer_volume)) table.add_row("Connected phases", convert_to_string(config.connected_phases)) table.add_row("Current control BOP CT type", config.current_control_bop_ct_type) table.add_row( "Current control BOP enabled", convert_to_string(config.current_control_bop_enabled), ) table.add_row( "Current control BOP fuse rating", f"{config.current_control_bop_fuse_rating}A", ) table.add_row( "Current control fixed charge current limit", convert_to_string(config.current_control_fixed_charge_current_limit), ) table.add_row("Ground monitoring", convert_to_string(config.ground_monitoring)) table.add_row( "Group load balancing enabled", convert_to_string(config.group_load_balancing_enabled), ) table.add_row( "Group load balancing fallback current", f"{config.group_load_balancing_fallback_current}A", ) table.add_row( "Group load balancing group ID", convert_to_string(config.group_load_balancing_group_id), ) table.add_row( "Group load balancing interface", config.group_load_balancing_interface ) table.add_row( "Group load balancing max current", f"{config.group_load_balancing_max_current}A", ) table.add_row("Group load balancing role", config.group_load_balancing_role) table.add_row( "LED intensity manual", convert_to_string(config.led_intensity_manual) ) table.add_row("LED intensity max", convert_to_string(config.led_intensity_max)) table.add_row("LED intensity min", convert_to_string(config.led_intensity_min)) table.add_row("LED intensity mode", config.led_intensity_mode) table.add_row("Local REST API access mode", config.local_rest_api_access_mode) table.add_row( "Local REST API allowed", convert_to_string(config.local_rest_api_allowed) ) table.add_row( "Local REST API enabled", convert_to_string(config.local_rest_api_enabled) ) table.add_row( "Local smart charging allowed", convert_to_string(config.local_smart_charging_allowed), ) table.add_row("Modbus server access mode", config.modbus_server_access_mode) table.add_row( "Modbus server allowed", convert_to_string(config.modbus_server_allowed) ) table.add_row( "Modbus server enabled", convert_to_string(config.modbus_server_enabled) ) table.add_row("Phase rotation", config.phase_rotation) table.add_row( "Power limit input DI1 inverse", convert_to_string(config.power_limit_input_di1_inverse), ) table.add_row( "Power limit input DI1 limit", f"{config.power_limit_input_di1_limit}A", ) table.add_row( "Power limit input DI2 inverse", convert_to_string(config.power_limit_input_di2_inverse), ) table.add_row( "Power limit input DI2 limit", f"{config.power_limit_input_di2_limit}A" ) table.add_row( "Power limit input enabled", convert_to_string(config.power_limit_input_enabled) ) table.add_row("Predefined CPO name", config.predefined_cpo_name) table.add_row( "Scheduled charging allowed", convert_to_string(config.scheduled_charging_allowed), ) table.add_row( "Scheduled charging enabled", convert_to_string(config.scheduled_charging_enabled), ) table.add_row("SECC OCPP active", convert_to_string(config.secc_ocpp_active)) table.add_row("SECC OCPP URI", config.secc_ocpp_uri) table.add_row( "Session manager charge without authentication", convert_to_string(config.session_manager_charge_without_authentication), ) table.add_row( "Solar charging allowed", convert_to_string(config.solar_charging_allowed) ) table.add_row( "Solar charging enabled", convert_to_string(config.solar_charging_enabled) ) table.add_row("Solar charging mode", config.solar_charging_mode) table.add_row( "Solar charging source parameters", convert_to_string(config.solar_charging_source_parameters), ) table.add_row("Solar charging source", config.solar_charging_source) table.add_row("Time zone", config.time_zone) table.add_row( "User defined charge limit current allowed", convert_to_string(config.user_defined_charge_limit_current_allowed), ) table.add_row( "User defined charge limit current", f"{config.user_defined_charge_limit_current}A", ) table.add_row( "User defined household power limit allowed", convert_to_string(config.user_defined_household_power_limit_allowed), ) table.add_row( "User defined household power limit enabled", convert_to_string(config.user_defined_household_power_limit_enabled), ) table.add_row( "User defined household power limit source", config.user_defined_household_power_limit_source, ) table.add_row( "User defined household power limit", f"{round(config.user_defined_household_power_limit / 1000, 3)} kW", ) table.add_row( "User keep socket locked", convert_to_string(config.user_keep_socket_locked) ) table.add_row( "VDE phase imbalance enabled", convert_to_string(config.vde_phase_imbalance_enabled), ) table.add_row("VDE phase imbalance limit", f"{config.vde_phase_imbalance_limit}A") table.add_row( "Web IF update helper", convert_to_string(config.web_if_update_helper) ) table.add_section() smart_charging_mode = "Unknown" if config.smart_charging is not None: smart_charging_mode = { SmartChargingMode.DEFAULT: "Default", SmartChargingMode.FAST_SOLAR: "Fast solar", SmartChargingMode.SMART_SOLAR: "Smart solar", SmartChargingMode.PURE_SOLAR: "Pure solar", SmartChargingMode.SCHEDULED: "Scheduled", }.get(config.smart_charging, "Unknown") table.add_row("Smart charging mode", smart_charging_mode) console.print(table) @cli.command("smart-charging") # pylint: disable=too-many-arguments,too-many-positional-arguments async def smart_charging( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], default: Annotated[ bool, typer.Option( help="Not limited by any strategy.", ), ] = False, fast_solar: Annotated[ bool, typer.Option( help="Fast charge with a mix of grid and solar power.", ), ] = False, smart_solar: Annotated[ bool, typer.Option( help="Charge with a smart mix of grid and solar power.", ), ] = False, pure_solar: Annotated[ bool, typer.Option( help="Charge only with solar power.", ), ] = False, scheduled: Annotated[ bool, typer.Option( help="Scheduled charging.", ), ] = False, ) -> None: """Control the smart charging mode.""" # Only one of the charging modes can be selected, and at least one must be selected. if sum([default, fast_solar, smart_solar, pure_solar, scheduled]) != 1 or not any( [default, fast_solar, smart_solar, pure_solar, scheduled] ): msg = ( "Exactly one of --default, --fast-solar, --smart-solar, " "--pure-solar or --scheduled must be used." ) raise typer.BadParameter(msg) with console.status("[cyan]Adjusting...", spinner="toggle12"): async with Peblar(host=host) as peblar: await peblar.login(password=password) if default: await peblar.smart_charging(SmartChargingMode.DEFAULT) if fast_solar: await peblar.smart_charging(SmartChargingMode.FAST_SOLAR) if smart_solar: await peblar.smart_charging(SmartChargingMode.SMART_SOLAR) if pure_solar: await peblar.smart_charging(SmartChargingMode.PURE_SOLAR) if scheduled: await peblar.smart_charging(SmartChargingMode.SCHEDULED) console.print("โœ…[green]Success!") @cli.command("ev") async def ev( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], charge_limit: Annotated[ int | None, typer.Option( help="Charge current limit in A", ), ] = None, force_single_phase: Annotated[ bool | None, typer.Option( help="Force single phase charging", ), ] = None, ) -> None: """Get the EV interface status of the Peblar charger.""" async with Peblar(host=host) as peblar: await peblar.login(password=password) async with await peblar.rest_api() as api: if charge_limit is not None or force_single_phase is not None: with console.status("[cyan]Adjusting...", spinner="toggle12"): await api.ev_interface( charge_current_limit=charge_limit * 1000 if charge_limit else None, force_single_phase=force_single_phase, ) console.print("โœ…[green]Success") ev_interface = await api.ev_interface() table = Table(title="Peblar EV interface information") table.add_column("Property", style="cyan bold") table.add_column("Value", style="bold") table.add_row( "Charge current limit", f"{round(ev_interface.charge_current_limit / 1000, 3)}A", ) table.add_row( "Charge current limit actual", f"{round(ev_interface.charge_current_limit_actual / 1000, 3)}A", ) table.add_row( "Charge current limit source", ev_interface.charge_current_limit_source ) cp_state = { CPState.NO_EV_CONNECTED: "EV not connected", CPState.CHARGING_SUSPENDED: "Charging suspended", CPState.CHARGING: "Charging", CPState.CHARGING_VENTILATION: "Charging, ventilation requested", CPState.ERROR: "Error; short or powered off", CPState.FAULT: "Fault; Charger is not operational", CPState.INVALID: "Invalid; Charger is not operational", }.get(ev_interface.cp_state, "Unknown") table.add_row("CP state", cp_state) table.add_row( "Force single phase", convert_to_string(ev_interface.force_single_phase) ) console.print(table) @cli.command("health") async def health( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], ) -> None: """Get the health status of the Peblar charger.""" async with Peblar(host=host) as peblar: await peblar.login(password=password) async with await peblar.rest_api() as api: data = await api.health() table = Table(title="Peblar API Health") table.add_column("Property", style="cyan bold") table.add_column("Value", style="bold") table.add_row("API Access mode", data.access_mode.value) table.add_row("API version", convert_to_string(data.api_version)) console.print(table) @cli.command("meter") async def meter( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], ) -> None: """Get meter status of the Peblar charger.""" async with Peblar(host=host) as peblar: await peblar.login(password=password) async with await peblar.rest_api() as api: meter_data = await api.meter() table = Table(title="Peblar meter status") table.add_column("Property", style="cyan bold") table.add_column("Value", style="bold") table.add_row("Energy session", f"{round(meter_data.energy_session / 1000, 3)}kWh") table.add_row("Energy total", f"{round(meter_data.energy_total / 1000, 3)}kWh") table.add_section() table.add_row("Total power", f"{meter_data.power_total}W") table.add_row("Power phase 1", f"{meter_data.power_phase_1}W") table.add_row("Power phase 2", f"{meter_data.power_phase_2}W") table.add_row("Power phase 3", f"{meter_data.power_phase_3}W") table.add_section() total_current = round( ( meter_data.current_phase_1 + meter_data.current_phase_2 + meter_data.current_phase_3 ) / 1000, 3, ) table.add_row("Total current", f"{total_current}A") table.add_row("Current Phase 1", f"{round(meter_data.current_phase_1 / 1000, 3)}A") table.add_row("Current Phase 2", f"{round(meter_data.current_phase_2 / 1000, 3)}A") table.add_row("Current Phase 3", f"{round(meter_data.current_phase_3 / 1000, 3)}A") table.add_section() table.add_row("Voltage Phase 1", f"{meter_data.voltage_phase_1 or 0}V") table.add_row("Voltage Phase 2", f"{meter_data.voltage_phase_2 or 0}V") table.add_row("Voltage Phase 3", f"{meter_data.voltage_phase_3 or 0}V") console.print(table) @cli.command("system") async def system( host: Annotated[ str, typer.Option( help="Peblar charger IP address or hostname", prompt="Host address", show_default=False, envvar="PEBLAR_HOST", ), ], password: Annotated[ str, typer.Option( help="Peblar charger login password", prompt="Password", show_default=False, hide_input=True, envvar="PEBLAR_PASSWORD", ), ], ) -> None: """Get the status of the Peblar charger.""" async with Peblar(host=host) as peblar: await peblar.login(password=password) async with await peblar.rest_api() as api: data = await api.system() table = Table(title="Peblar charger system status") table.add_column("Property", style="cyan bold") table.add_column("Value", style="bold") table.add_row( "Active error codes", ",".join(data.active_error_codes) or "No errors" ) table.add_row( "Active warning codes", ",".join(data.active_warning_codes) or "No warnings" ) table.add_section() table.add_row("Phase count", convert_to_string(data.phase_count)) table.add_row( "Force of single phase allowed", convert_to_string(data.force_single_phase_allowed), ) table.add_section() table.add_row("Firmware version", data.firmware_version) table.add_row("Product serial number", data.product_serial_number) table.add_row("Product part number", data.product_part_number) table.add_section() table.add_row("Uptime", f"{data.uptime} seconds") if data.wlan_signal_strength is not None: table.add_row("WLAN signal strength", f"{data.wlan_signal_strength} dBm") else: table.add_row("WLAN signal strength", "WLAN not connected") if data.cellular_signal_strength is not None: table.add_row( "Cellular signal strength", f"{data.cellular_signal_strength} dBm" ) else: table.add_row("Cellular signal strength", "Cellular not connected") console.print(table) @cli.command("scan") async def scan() -> None: """Scan for Peblar chargers on the network.""" zeroconf = AsyncZeroconf() background_tasks = set() table = Table( title="\n\nFound Peblar chargers", header_style="cyan bold", show_lines=True ) table.add_column("Addresses") table.add_column("Serial number") table.add_column("Software version") def async_on_service_state_change( zeroconf: Zeroconf, service_type: str, name: str, state_change: ServiceStateChange, ) -> None: """Handle service state changes.""" if state_change is not ServiceStateChange.Added: return future = asyncio.ensure_future( async_display_service_info(zeroconf, service_type, name) ) background_tasks.add(future) future.add_done_callback(background_tasks.discard) async def async_display_service_info( zeroconf: Zeroconf, service_type: str, name: str ) -> None: """Retrieve and display service info.""" info = AsyncServiceInfo(service_type, name) await info.async_request(zeroconf, 3000) if info is None: return if info.properties is None or not str(info.server).startswith("PBLR-"): return console.print(f"[cyan bold]Found service {info.server}: is a Peblar charger ๐ŸŽ‰") table.add_row( f"{str(info.server).rstrip('.')}\n" + ", ".join(info.parsed_scoped_addresses()), info.properties[b"sn"].decode(), # type: ignore[union-attr] info.properties[b"version"].decode(), # type: ignore[union-attr] ) console.print("[green]Scanning for Peblar chargers...") console.print("[red]Press Ctrl-C to exit\n") with Live(table, console=console, refresh_per_second=4): browser = AsyncServiceBrowser( zeroconf.zeroconf, "_http._tcp.local.", handlers=[async_on_service_state_change], ) try: while True: # noqa: ASYNC110 await asyncio.sleep(0.5) except KeyboardInterrupt: pass finally: console.print("\n[green]Control-C pressed, stopping scan") await browser.async_cancel() await zeroconf.async_close() if __name__ == "__main__": cli() frenck-python-peblar-e4c64a5/src/peblar/cli/async_typer.py000066400000000000000000000142341474441165200237120ustar00rootroot00000000000000"""Asynchronous Python client for Peblar EV chargers. Adaptation of the snippet/code from: - https://github.com/tiangolo/typer/issues/88#issuecomment-1613013597 - https://github.com/argilla-io/argilla/blob/e77ca86c629a492019f230ac55ebde207b280xc9c/src/argilla/cli/typer_ext.py """ # Copyright 2021-present, the Recognai S.L. team. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import annotations import asyncio from collections.abc import Callable # pylint: disable=import-error from functools import wraps from typing import ( TYPE_CHECKING, Any, ParamSpec, TypeVar, ) from typer import Exit from typer import Typer as SyncTyper if TYPE_CHECKING: from collections.abc import Coroutine from typer.core import TyperCommand, TyperGroup _P = ParamSpec("_P") _R = TypeVar("_R") HandleErrorFunc = Callable[[Any], None] class AsyncTyper(SyncTyper): """A Typer subclass that supports async.""" error_handlers: dict[type[Exception], HandleErrorFunc] # pylint: disable-next=too-many-arguments, too-many-locals def callback( # type: ignore[override] # noqa: PLR0913 self, *, cls: type[TyperGroup] | None = None, invoke_without_command: bool = False, no_args_is_help: bool = False, subcommand_metavar: str | None = None, chain: bool = False, result_callback: Callable[..., Any] | None = None, context_settings: dict[Any, Any] | None = None, # pylint: disable-next=redefined-builtin help: str | None = None, # noqa: A002 epilog: str | None = None, short_help: str | None = None, options_metavar: str = "[OPTIONS]", add_help_option: bool = True, hidden: bool = False, deprecated: bool = False, rich_help_panel: str | None = None, ) -> Callable[ [Callable[_P, Coroutine[Any, Any, _R]]], Callable[_P, Coroutine[Any, Any, _R]], ]: """Create a new typer callback.""" super_callback = super().callback( cls=cls, invoke_without_command=invoke_without_command, no_args_is_help=no_args_is_help, subcommand_metavar=subcommand_metavar, chain=chain, result_callback=result_callback, context_settings=context_settings, help=help, epilog=epilog, short_help=short_help, options_metavar=options_metavar, add_help_option=add_help_option, hidden=hidden, deprecated=deprecated, rich_help_panel=rich_help_panel, ) def decorator( func: Callable[_P, Coroutine[Any, Any, _R]], ) -> Callable[_P, Coroutine[Any, Any, _R]]: if asyncio.iscoroutinefunction(func): @wraps(func) def sync_func(*_args: _P.args, **_kwargs: _P.kwargs) -> _R: return asyncio.run(func(*_args, **_kwargs)) super_callback(sync_func) else: super_callback(func) return func return decorator # pylint: disable-next=too-many-arguments def command( # type: ignore[override] # noqa: PLR0913 self, name: str | None = None, *, cls: type[TyperCommand] | None = None, context_settings: dict[Any, Any] | None = None, # pylint: disable-next=redefined-builtin help: str | None = None, # noqa: A002 epilog: str | None = None, short_help: str | None = None, options_metavar: str = "[OPTIONS]", add_help_option: bool = True, no_args_is_help: bool = False, hidden: bool = False, deprecated: bool = False, # Rich settings rich_help_panel: str | None = None, ) -> Callable[ [Callable[_P, Coroutine[Any, Any, _R]]], Callable[_P, Coroutine[Any, Any, _R]], ]: """Create a new typer command.""" super_command = super().command( name, cls=cls, context_settings=context_settings, help=help, epilog=epilog, short_help=short_help, options_metavar=options_metavar, add_help_option=add_help_option, no_args_is_help=no_args_is_help, hidden=hidden, deprecated=deprecated, rich_help_panel=rich_help_panel, ) def decorator( func: Callable[_P, Coroutine[Any, Any, _R]], ) -> Callable[_P, Coroutine[Any, Any, _R]]: if asyncio.iscoroutinefunction(func): @wraps(func) def sync_func(*_args: _P.args, **_kwargs: _P.kwargs) -> _R: return asyncio.run(func(*_args, **_kwargs)) super_command(sync_func) else: super_command(func) return func return decorator def error_handler(self, exc: type[Exception]) -> Callable[[HandleErrorFunc], None]: """Register an error handler for a given exception.""" if not hasattr(self, "error_handlers"): self.error_handlers = {} def decorator(func: HandleErrorFunc) -> None: self.error_handlers[exc] = func return decorator def __call__(self, *args: Any, **kwargs: Any) -> Any: """Call the typer app.""" try: return super().__call__(*args, **kwargs) except Exit: raise # pylint: disable-next=broad-except except Exception as e: if ( not hasattr(self, "error_handlers") or (handler := self.error_handlers.get(type(e))) is None ): raise return handler(e) frenck-python-peblar-e4c64a5/src/peblar/cli/ruff.toml000066400000000000000000000002611474441165200226320ustar00rootroot00000000000000# This extend our general Ruff rules specifically for the examples extend = "../../../pyproject.toml" lint.extend-ignore = [ "FBT002", "PLR0913", "PLR0915", "RUF100" ] frenck-python-peblar-e4c64a5/src/peblar/const.py000066400000000000000000000105711474441165200217310ustar00rootroot00000000000000"""Asynchronous Python client for Peblar EV chargers.""" from enum import IntEnum, StrEnum class AccessMode(StrEnum): """Peblar access mode.""" READ_WRITE = "ReadWrite" """Read and write access.""" READ_ONLY = "ReadOnly" """Read only access.""" class SolarChargingMode(StrEnum): """Peblar solar charging mode.""" MAX_SOLAR = "MaxSolar" """Fast charge with a mix of grid and solar power.""" OPTIMIZED_SOLAR = "OptimizedSolar" """Charge with a smart mix of grid and solar power.""" PURE_SOLAR = "PureSolar" """Charge only with solar power.""" class SoundVolume(IntEnum): """Peblar sound volume.""" OFF = 0 """Sound off.""" LOW = 1 """Low sound volume.""" LOW_MEDIUM = 2 """Low medium sound volume. NOTE: Not present in the UI.""" MEDIUM = 3 """Medium sound volume.""" HIGH = 4 """High sound volume.""" class LedIntensityMode(StrEnum): """Peblar LED intensity mode.""" AUTO = "Auto" """Automatic LED intensity.""" FIXED = "Fixed" """Fixed LED intensity.""" class SmartChargingMode(StrEnum): """Peblar smart charging mode.""" DEFAULT = "default" """Not limited by any strategy.""" FAST_SOLAR = "fast_solar" """Fast charge with a mix of grid and solar power.""" SMART_SOLAR = "smart_solar" """Charge with a smart mix of grid and solar power.""" PURE_SOLAR = "pure_solar" """Charge only with solar power.""" SCHEDULED = "scheduled" "Charge only within the defined schedule." class ChargeLimiter(StrEnum): """Peblar charge limiter.""" CHARGING_CABLE = "Charging cable" """Charging limited by the maximum rated current of the attached cable.""" CURRENT_LIMITER = "Current limiter" """Charging limited by the user-defined maximum current.""" DYNAMIC_LOAD_BALANCING = "Dynamic load balancing" """Charging limited by the maximum current due to dynamic load balancing.""" EXTERNAL_POWER_LIMIT = "External power limit" """Charging limited by the maximum current due to external power limit.""" GROUP_LOAD_BALANCING = "Group load balancing" """Charging limited by the maximum current due to group load balancing.""" HARDWARE_LIMITATION = "Hardware limitation" """Charging limited by the maximum current due to hardware limitation.""" HIGH_TEMPERATURE = "High temperature" """Charging is limited due to high temperature in charger.""" HOUSEHOLD_POWER_LIMIT = "Household power limit" """Charging limited by total power consumption of the household.""" INSTALLATION_LIMIT = "Installation limit" """Charging limited by the maximum installation current configured.""" LOCAL_MODBUS_API = "Local Modbus API" """Charging limited by the maximum current by local Modbus API.""" LOCAL_REST_API = "Local REST API" """Charging limited by the maximum current by local REST API.""" LOCAL_SCHEDULED_CHARGING = "Local scheduled charging" """Charging limited by the local schedule.""" OCPP_SMART_CHARGING = "OCPP smart charging" """Charging limited by the maximum current by OCPP profile.""" OVERCURRENT_PROTECTION = "Overcurrent protection" """Charging limited by the maximum current due to overcurrent protection.""" PHASE_IMBALANCE = "Phase imbalance" """Charging limited by the maximum current due to phase imbalance.""" POWER_FACTOR = "Power factor" """Charging limited by the maximum current due to power factor.""" SOLAR_CHARGING = "Solar charging" """Charging limited by the maximum current due to solar charging.""" class CPState(StrEnum): """Peblar CP state.""" NO_EV_CONNECTED = "State A" """No EV connected.""" CHARGING_SUSPENDED = "State B" """EV connected, byt charging suspended by EV or charger.""" CHARGING = "State C" """EV connected and charging.""" CHARGING_VENTILATION = "State D" """EV connected and charging, but ventilation requested (unused).""" ERROR = "State E" """Error state; Short or powered off.""" FAULT = "State F" """Fault state; Charger is not operational.""" INVALID = "Invalid" """Invalid CP measured.""" UNKNOWN = "Unknown" """CP signal cannot be measured.""" class PackageType(StrEnum): """Peblar package type.""" FIRMWARE = "Firmware" """Firmware package.""" CUSTOMIZATION = "Customization" """Customization package.""" frenck-python-peblar-e4c64a5/src/peblar/exceptions.py000066400000000000000000000011411474441165200227550ustar00rootroot00000000000000"""Asynchronous Python client for Peblar EV chargers.""" class PeblarError(Exception): """Generic Peblar exception.""" class PeblarConnectionError(PeblarError): """Peblar connection exception.""" class PeblarConnectionTimeoutError(PeblarConnectionError): """Peblar connection timeout exception.""" class PeblarResponseError(PeblarError): """Peblar unexpected response exception.""" class PeblarAuthenticationError(PeblarResponseError): """Peblar connection exception.""" class PeblarUnsupportedFirmwareVersionError(PeblarError): """Peblar unsupported version exception.""" frenck-python-peblar-e4c64a5/src/peblar/models.py000066400000000000000000000550051474441165200220670ustar00rootroot00000000000000"""Asynchronous Python client for Peblar EV chargers.""" from __future__ import annotations from dataclasses import dataclass, field from typing import Any import orjson from awesomeversion import AwesomeVersion from mashumaro import field_options from mashumaro.config import BaseConfig from mashumaro.mixins.orjson import DataClassORJSONMixin from mashumaro.types import SerializationStrategy from .const import ( AccessMode, ChargeLimiter, CPState, LedIntensityMode, PackageType, SmartChargingMode, SolarChargingMode, SoundVolume, ) from .utils import get_awesome_version class AwesomeVersionSerializationStrategy(SerializationStrategy, use_annotations=True): """Serialization strategy for AwesomeVersion objects.""" def serialize(self, value: AwesomeVersion) -> str: """Serialize AwesomeVersion object to string.""" return str(value) def deserialize(self, value: str) -> AwesomeVersion | None: """Deserialize string to AwesomeVersion object.""" version = get_awesome_version(value) if not version.valid: return None return version class BaseModel(DataClassORJSONMixin): """Base model for all Peblar models.""" # pylint: disable-next=too-few-public-methods class Config(BaseConfig): """Mashumaro configuration.""" serialize_by_alias = True serialization_strategy = { # noqa: RUF012 AwesomeVersion: AwesomeVersionSerializationStrategy() } omit_none = True @dataclass(kw_only=True) class PeblarApiToken(BaseModel): """Object holding the API token for the Peblar charger.""" api_token: str = field(metadata=field_options(alias="ApiToken")) @dataclass(kw_only=True) class PeblarReboot(BaseModel): """Object holding the Pedblar reboot playload.""" reboot_type: str = field( default="HardReboot", metadata=field_options(alias="RebootType") ) @dataclass(kw_only=True) class PeblarUpdate(BaseModel): """Object holding the update payload for the Peblar charger.""" package_type: PackageType = field(metadata=field_options(alias="Package-Type")) @dataclass(kw_only=True) class PeblarLocalRestApiAccess(BaseModel): """Object holding the local REST API configuration of a Peblar charger.""" access_mode: AccessMode | None = field( default=None, metadata=field_options(alias="LocalRestApiAccessMode") ) enabled: bool | None = field( default=None, metadata=field_options(alias="LocalRestApiEnable") ) @dataclass(kw_only=True) class PeblarModbusApiAccess(BaseModel): """Object holding the Modbus API configuration of a Peblar charger.""" access_mode: AccessMode | None = field( default=None, metadata=field_options(alias="ModbusServerAccessMode") ) enabled: bool | None = field( default=None, metadata=field_options(alias="ModbusServerEnable") ) @dataclass(kw_only=True) class PeblarLogin(BaseModel): """Login request for Peblar chargers.""" password: str = field(metadata=field_options(alias="Password")) persistent_session: bool = field( default=False, metadata=field_options(alias="PersistentSession") ) @dataclass(kw_only=True) class PeblarVersions(BaseModel): """Object holding the version information of the Peblar charger.""" customization: str | None = field( default=None, metadata=field_options(alias="Customization") ) firmware: str | None = field(default=None, metadata=field_options(alias="Firmware")) customization_version: AwesomeVersion | None = None firmware_version: AwesomeVersion | None = None @classmethod def __pre_deserialize__(cls, d: dict[Any, Any]) -> dict[Any, Any]: """Pre deserialize hook for PeblarVersions object.""" # Strip off everything until the first `-` for the customization # for AwesomeVersion to parse it correctly. # E.g., `Peblar-1.8` if customization := d.get("Customization"): d["customization_version"] = customization.split("-")[-1] # Strip off everything after the first + for the firmware # for AwesomeVersion to parse it correctly. # E.g., `1.6.1+1+WL-1.0` if firmware := d.get("Firmware"): d["firmware_version"] = firmware.split("+")[0] return d @dataclass(kw_only=True) # pylint: disable-next=too-many-instance-attributes class PeblarSystemInformation(BaseModel): """Object holding information about the Peblar charger.""" bop_calibration_current_gain_a: int | None = field( default=None, metadata=field_options(alias="BopCalIGainA") ) bop_calibration_current_gain_b: int | None = field( default=None, metadata=field_options(alias="BopCalIGainB") ) bop_calibration_current_gain_c: int | None = field( default=None, metadata=field_options(alias="BopCalIGainC") ) can_change_charging_phases: bool = field( metadata=field_options(alias="CanChangeChargingPhases") ) can_charge_single_phase: bool = field( metadata=field_options(alias="CanChargeSinglePhase") ) can_charge_three_phases: bool = field( metadata=field_options(alias="CanChargeThreePhases") ) customer_id: str = field(metadata=field_options(alias="CustomerId")) customer_update_package_public_key: str = field( metadata=field_options(alias="CustomerUpdatePackagePubKey") ) ethernet_mac_address: str = field(metadata=field_options(alias="EthMacAddr")) firmware_version: str = field(metadata=field_options(alias="FwIdent")) hostname: str = field(metadata=field_options(alias="Hostname")) hardware_fixed_cable_rating: int = field( metadata=field_options(alias="HwFixedCableRating") ) hardware_firmware_compatibility: str = field( metadata=field_options(alias="HwFwCompat") ) hardware_has_bop: bool = field(metadata=field_options(alias="HwHasBop")) hardware_has_buzzer: bool = field(metadata=field_options(alias="HwHasBuzzer")) hardware_has_eichrecht_laser_marking: bool = field( metadata=field_options(alias="HwHasEichrechtLaserMarking") ) hardware_has_ethernet: bool = field(metadata=field_options(alias="HwHasEthernet")) hardware_has_led: bool = field(metadata=field_options(alias="HwHasLed")) hardware_has_lte: bool = field(metadata=field_options(alias="HwHasLte")) hardware_has_meter: bool = field(metadata=field_options(alias="HwHasMeter")) hardware_has_meter_display: bool = field( metadata=field_options(alias="HwHasMeterDisplay") ) hardware_has_plc: bool = field(metadata=field_options(alias="HwHasPlc")) hardware_has_rfid: bool = field(metadata=field_options(alias="HwHasRfid")) hardware_has_rs485: bool = field(metadata=field_options(alias="HwHasRs485")) hardware_has_socket: bool = field(metadata=field_options(alias="HwHasSocket")) hardware_has_tpm: bool = field(metadata=field_options(alias="HwHasTpm")) hardware_has_wlan: bool = field(metadata=field_options(alias="HwHasWlan")) hardware_max_current: int = field(metadata=field_options(alias="HwMaxCurrent")) hardware_one_or_three_phase: int = field( metadata=field_options(alias="HwOneOrThreePhase") ) mainboard_part_number: str = field(metadata=field_options(alias="MainboardPn")) mainboard_serial_number: str = field(metadata=field_options(alias="MainboardSn")) meter_calibration_current_gain_a: int = field( metadata=field_options(alias="MeterCalIGainA") ) meter_calibration_current_gain_b: int = field( metadata=field_options(alias="MeterCalIGainB") ) meter_calibration_current_gain_c: int = field( metadata=field_options(alias="MeterCalIGainC") ) meter_calibration_current_rms_offset_a: int = field( metadata=field_options(alias="MeterCalIRmsOffsetA") ) meter_calibration_current_rms_offset_b: int = field( metadata=field_options(alias="MeterCalIRmsOffsetB") ) meter_calibration_current_rms_offset_c: int = field( metadata=field_options(alias="MeterCalIRmsOffsetC") ) meter_calibration_phase_a: int = field( metadata=field_options(alias="MeterCalPhaseA") ) meter_calibration_phase_b: int = field( metadata=field_options(alias="MeterCalPhaseB") ) meter_calibration_phase_c: int = field( metadata=field_options(alias="MeterCalPhaseC") ) meter_calibration_voltage_gain_a: int = field( metadata=field_options(alias="MeterCalVGainA") ) meter_calibration_voltage_gain_b: int = field( metadata=field_options(alias="MeterCalVGainB") ) meter_calibration_voltage_gain_c: int = field( metadata=field_options(alias="MeterCalVGainC") ) meter_firmware_version: str = field(metadata=field_options(alias="MeterFwIdent")) product_model_name: str = field(metadata=field_options(alias="ProductModelName")) product_number: str = field(metadata=field_options(alias="ProductPn")) product_serial_number: str = field(metadata=field_options(alias="ProductSn")) product_vendor_name: str = field(metadata=field_options(alias="ProductVendorName")) wlan_ap_mac_address: str = field(metadata=field_options(alias="WlanApMacAddr")) wlan_mac_address: str = field(metadata=field_options(alias="WlanStaMacAddr")) @dataclass(kw_only=True) # pylint: disable-next=too-many-instance-attributes class PeblarUserConfiguration(BaseModel): """Object holding user configuration of a Peblar charger.""" bop_fallback_current: int = field( metadata=field_options(alias="BopFallbackCurrent") ) bop_home_wizard_address: str = field( metadata=field_options(alias="BopHomeWizardAddress") ) bop_source: str = field(metadata=field_options(alias="BopSource")) bop_source_parameters: str = field( metadata=field_options(alias="BopSourceParameters") ) connected_phases: int = field(metadata=field_options(alias="ConnectedPhases")) current_control_bop_ct_type: str = field( metadata=field_options(alias="CurrentCtrlBopCtType") ) current_control_bop_enabled: bool = field( metadata=field_options(alias="CurrentCtrlBopEnable") ) current_control_bop_fuse_rating: int = field( metadata=field_options(alias="CurrentCtrlBopFuseRating") ) current_control_fixed_charge_current_limit: int = field( metadata=field_options(alias="CurrentCtrlFixedChargeCurrentLimit") ) ground_monitoring: bool = field(metadata=field_options(alias="GroundMonitoring")) group_load_balancing_enabled: bool = field( metadata=field_options(alias="GroupLoadBalancingEnable") ) group_load_balancing_fallback_current: int = field( metadata=field_options(alias="GroupLoadBalancingFallbackCurrent") ) group_load_balancing_group_id: int = field( metadata=field_options(alias="GroupLoadBalancingGroupId") ) group_load_balancing_interface: str = field( metadata=field_options(alias="GroupLoadBalancingInterface") ) group_load_balancing_max_current: int = field( metadata=field_options(alias="GroupLoadBalancingMaxCurrent") ) group_load_balancing_role: str = field( metadata=field_options(alias="GroupLoadBalancingRole") ) buzzer_volume: SoundVolume = field(metadata=field_options(alias="HmiBuzzerVolume")) led_intensity_manual: int = field( metadata=field_options(alias="HmiLedIntensityManual") ) led_intensity_max: int = field(metadata=field_options(alias="HmiLedIntensityMax")) led_intensity_min: int = field(metadata=field_options(alias="HmiLedIntensityMin")) led_intensity_mode: LedIntensityMode = field( metadata=field_options(alias="HmiLedIntensityMode") ) local_rest_api_access_mode: AccessMode = field( metadata=field_options(alias="LocalRestApiAccessMode") ) local_rest_api_allowed: bool = field( metadata=field_options(alias="LocalRestApiAllowed") ) local_rest_api_enabled: bool = field( metadata=field_options(alias="LocalRestApiEnable") ) local_smart_charging_allowed: bool = field( metadata=field_options(alias="LocalSmartChargingAllowed") ) modbus_server_access_mode: AccessMode = field( metadata=field_options(alias="ModbusServerAccessMode") ) modbus_server_allowed: bool = field( metadata=field_options(alias="ModbusServerAllowed") ) modbus_server_enabled: bool = field( metadata=field_options(alias="ModbusServerEnable") ) phase_rotation: str = field(metadata=field_options(alias="PhaseRotation")) power_limit_input_di1_inverse: bool = field( metadata=field_options(alias="PowerLimitInputDi1Inverse") ) power_limit_input_di1_limit: int = field( metadata=field_options(alias="PowerLimitInputDi1Limit") ) power_limit_input_di2_inverse: bool = field( metadata=field_options(alias="PowerLimitInputDi2Inverse") ) power_limit_input_di2_limit: int = field( metadata=field_options(alias="PowerLimitInputDi2Limit") ) power_limit_input_enabled: bool = field( metadata=field_options(alias="PowerLimitInputEnable") ) predefined_cpo_name: str = field(metadata=field_options(alias="PredefinedCpoName")) scheduled_charging_allowed: bool = field( metadata=field_options(alias="ScheduledChargingAllowed") ) scheduled_charging_enabled: bool = field( metadata=field_options(alias="ScheduledChargingEnable") ) secc_ocpp_active: bool = field(metadata=field_options(alias="SeccOcppActive")) secc_ocpp_uri: str = field(metadata=field_options(alias="SeccOcppUri")) session_manager_charge_without_authentication: bool = field( metadata=field_options(alias="SessionManagerChargeWithoutAuth") ) solar_charging_allowed: bool = field( metadata=field_options(alias="SolarChargingAllowed") ) solar_charging_enabled: bool = field( metadata=field_options(alias="SolarChargingEnable") ) solar_charging_mode: SolarChargingMode = field( metadata=field_options(alias="SolarChargingMode") ) solar_charging_source: str = field( metadata=field_options(alias="SolarChargingSource") ) solar_charging_source_parameters: dict[str, Any] = field( metadata=field_options(alias="SolarChargingSourceParameters") ) time_zone: str = field(metadata=field_options(alias="TimeZone")) user_defined_charge_limit_current: int = field( metadata=field_options(alias="UserDefinedChargeLimitCurrent") ) user_defined_charge_limit_current_allowed: bool = field( metadata=field_options(alias="UserDefinedChargeLimitCurrentAllowed") ) user_defined_household_power_limit: int = field( metadata=field_options(alias="UserDefinedHouseholdPowerLimit") ) user_defined_household_power_limit_allowed: bool = field( metadata=field_options(alias="UserDefinedHouseholdPowerLimitAllowed") ) user_defined_household_power_limit_enabled: bool = field( metadata=field_options(alias="UserDefinedHouseholdPowerLimitEnable") ) user_defined_household_power_limit_source: str = field( metadata=field_options(alias="UserDefinedHouseholdPowerLimitSource") ) user_keep_socket_locked: bool = field( metadata=field_options(alias="UserKeepSocketLocked") ) vde_phase_imbalance_enabled: bool = field( metadata=field_options(alias="VDEPhaseImbalanceEnable") ) vde_phase_imbalance_limit: int = field( metadata=field_options(alias="VDEPhaseImbalanceLimit") ) web_if_update_helper: bool = field( metadata=field_options(alias="WebIfUpdateHelper") ) # Replicated field from the Peblar UI smart_charging: SmartChargingMode | None = None @classmethod def __pre_deserialize__(cls, d: dict[Any, Any]) -> dict[Any, Any]: """Pre deserialize hook for PeblarUserConfiguration object.""" d["SolarChargingSourceParameters"] = orjson.loads( d.get("SolarChargingSourceParameters") or "{}" ) d["BopSourceParameters"] = orjson.loads(d.get("BopSourceParameters") or "{}") return d @classmethod def __post_deserialize__( cls, obj: PeblarUserConfiguration ) -> PeblarUserConfiguration: """Post deserialize hook for PeblarUserConfiguration object.""" if not obj.scheduled_charging_enabled and not obj.solar_charging_enabled: obj.smart_charging = SmartChargingMode.DEFAULT elif obj.scheduled_charging_enabled and not obj.solar_charging_enabled: obj.smart_charging = SmartChargingMode.SCHEDULED elif not obj.scheduled_charging_enabled and obj.solar_charging_enabled: if obj.solar_charging_mode == SolarChargingMode.MAX_SOLAR: obj.smart_charging = SmartChargingMode.FAST_SOLAR elif obj.solar_charging_mode == SolarChargingMode.OPTIMIZED_SOLAR: obj.smart_charging = SmartChargingMode.SMART_SOLAR elif obj.solar_charging_mode == SolarChargingMode.PURE_SOLAR: obj.smart_charging = SmartChargingMode.PURE_SOLAR return obj @dataclass(kw_only=True) class PeblarSmartCharging(BaseModel): """Object holding the configuration of the Peblar charger.""" solar_charging_enable: bool | None = field( default=None, metadata=field_options(alias="SolarChargingEnable") ) solar_charging_mode: SolarChargingMode | None = field( default=None, metadata=field_options(alias="SolarChargingMode") ) scheduled_charging_enable: bool | None = field( default=None, metadata=field_options(alias="ScheduledChargingEnable") ) # Replicated field from the Peblar UI smart_charging: SmartChargingMode | None = field( default=None, metadata=field_options(serialize="omit") ) def __post_init__(self) -> None: """Post init hook for PeblarSmartCharging object.""" if self.smart_charging: if self.smart_charging == SmartChargingMode.DEFAULT: self.scheduled_charging_enable = False self.solar_charging_enable = False elif self.smart_charging == SmartChargingMode.SCHEDULED: self.scheduled_charging_enable = True self.solar_charging_enable = False elif self.smart_charging == SmartChargingMode.FAST_SOLAR: self.scheduled_charging_enable = False self.solar_charging_enable = True self.solar_charging_mode = SolarChargingMode.MAX_SOLAR elif self.smart_charging == SmartChargingMode.SMART_SOLAR: self.scheduled_charging_enable = False self.solar_charging_enable = True self.solar_charging_mode = SolarChargingMode.OPTIMIZED_SOLAR elif self.smart_charging == SmartChargingMode.PURE_SOLAR: self.scheduled_charging_enable = False self.solar_charging_enable = True self.solar_charging_mode = SolarChargingMode.PURE_SOLAR @dataclass(kw_only=True) class PeblarHealth(BaseModel): """Object holding the health information of the Peblar charger.""" access_mode: AccessMode = field(metadata=field_options(alias="AccessMode")) api_version: AwesomeVersion = field(metadata=field_options(alias="ApiVersion")) @dataclass(kw_only=True) # pylint: disable-next=too-many-instance-attributes class PeblarSystem(BaseModel): """Object holding the system information of the Peblar charger.""" active_error_codes: list[str] = field( metadata=field_options(alias="ActiveErrorCodes") ) active_warning_codes: list[str] = field( metadata=field_options(alias="ActiveWarningCodes") ) cellular_signal_strength: int | None = field( metadata=field_options(alias="CellularSignalStrength") ) firmware_version: str = field(metadata=field_options(alias="FirmwareVersion")) force_single_phase_allowed: bool = field( metadata=field_options(alias="Force1PhaseAllowed") ) phase_count: int = field(metadata=field_options(alias="PhaseCount")) product_part_number: str = field(metadata=field_options(alias="ProductPn")) product_serial_number: str = field(metadata=field_options(alias="ProductSn")) uptime: int = field(metadata=field_options(alias="Uptime")) wlan_signal_strength: int | None = field( metadata=field_options(alias="WlanSignalStrength") ) @dataclass(kw_only=True) class PeblarEVInterface(BaseModel): """Object holding the EV interface information of the Peblar charger.""" charge_current_limit: int = field( metadata=field_options(alias="ChargeCurrentLimit") ) charge_current_limit_actual: int = field( metadata=field_options(alias="ChargeCurrentLimitActual") ) charge_current_limit_source: ChargeLimiter = field( metadata=field_options(alias="ChargeCurrentLimitSource") ) cp_state: CPState = field(metadata=field_options(alias="CpState")) force_single_phase: bool = field(metadata=field_options(alias="Force1Phase")) @dataclass(kw_only=True) class PeblarEVInterfaceChange(BaseModel): """Object holding the EV interface change payload.""" charge_current_limit: int | None = field( default=None, metadata=field_options(alias="ChargeCurrentLimit") ) force_single_phase: bool | None = field( default=None, metadata=field_options(alias="Force1Phase") ) @dataclass(kw_only=True) # pylint: disable-next=too-many-instance-attributes class PeblarMeter(BaseModel): """Object holding the meter information of the Peblar charger.""" current_phase_1: int = field(metadata=field_options(alias="CurrentPhase1")) current_phase_2: int = field(metadata=field_options(alias="CurrentPhase2")) current_phase_3: int = field(metadata=field_options(alias="CurrentPhase3")) energy_session: int = field(metadata=field_options(alias="EnergySession")) energy_total: int = field(metadata=field_options(alias="EnergyTotal")) power_phase_1: int = field(metadata=field_options(alias="PowerPhase1")) power_phase_2: int = field(metadata=field_options(alias="PowerPhase2")) power_phase_3: int = field(metadata=field_options(alias="PowerPhase3")) power_total: int = field(metadata=field_options(alias="PowerTotal")) voltage_phase_1: int | None = field(metadata=field_options(alias="VoltagePhase1")) voltage_phase_2: int | None = field(metadata=field_options(alias="VoltagePhase2")) voltage_phase_3: int | None = field(metadata=field_options(alias="VoltagePhase3")) @property def current_total(self) -> int: """Return the total current of the Peblar charger.""" return self.current_phase_1 + self.current_phase_2 + self.current_phase_3 frenck-python-peblar-e4c64a5/src/peblar/peblar.py000066400000000000000000000302611474441165200220460ustar00rootroot00000000000000"""Asynchronous Python client for Peblar EV chargers.""" from __future__ import annotations import asyncio import socket from dataclasses import dataclass from typing import TYPE_CHECKING, Self import backoff import orjson from aiohttp import ClientResponseError, CookieJar, hdrs from aiohttp.client import ClientError, ClientSession from yarl import URL from .exceptions import ( PeblarAuthenticationError, PeblarConnectionError, PeblarConnectionTimeoutError, PeblarError, ) from .models import ( BaseModel, PeblarApiToken, PeblarEVInterface, PeblarEVInterfaceChange, PeblarHealth, PeblarLocalRestApiAccess, PeblarLogin, PeblarMeter, PeblarModbusApiAccess, PeblarReboot, PeblarSmartCharging, PeblarSystem, PeblarSystemInformation, PeblarUpdate, PeblarUserConfiguration, PeblarVersions, ) if TYPE_CHECKING: from peblar.const import AccessMode, PackageType, SmartChargingMode @dataclass(kw_only=True) class Peblar: """Main class for handling connections with a Peblar EV chargers.""" host: str request_timeout: float = 8 session: ClientSession | None = None _close_session: bool = False def __post_init__(self) -> None: """Initialize the Peblar object.""" self.url = URL.build(scheme="http", host=self.host, path="/api/v1/") @backoff.on_exception( backoff.expo, PeblarConnectionError, max_tries=3, logger=None, ) async def request( self, uri: URL, *, method: str = hdrs.METH_GET, data: BaseModel | None = None, ) -> str: """Handle a request to a Peblar charger.""" if self.session is None: self.session = ClientSession( cookie_jar=CookieJar(unsafe=True), json_serialize=orjson.dumps, # type: ignore[arg-type] ) self._close_session = True try: async with asyncio.timeout(self.request_timeout): response = await self.session.request( method=method, url=self.url.join(uri), headers={"Content-Type": "application/json"}, data=data.to_json() if data else None, ) response.raise_for_status() except TimeoutError as exception: msg = "Timeout occurred while connecting to the Peblar charger" raise PeblarConnectionTimeoutError(msg) from exception except ClientResponseError as exception: if exception.status == 401: msg = "Authentication error. Provided password is invalid." raise PeblarAuthenticationError(msg) from exception msg = "Error occurred while communicating to the Peblar charger" raise PeblarError(msg) from exception except ( ClientError, socket.gaierror, ) as exception: msg = "Error occurred while communicating to the Peblar charger" raise PeblarConnectionError(msg) from exception return await response.text() async def login(self, *, password: str) -> None: """Login into the Peblar charger.""" await self.request( URL("auth/login"), method=hdrs.METH_POST, data=PeblarLogin( password=password, ), ) async def rest_api( self, *, enable: bool | None = None, access_mode: AccessMode | None = None, ) -> PeblarApi: """Get and control access to the REST API.""" user = await self.user_configuration() if not user.local_rest_api_allowed: msg = "The use of the local REST API is not allowed for this device." raise PeblarError(msg) if enable is not None and user.local_rest_api_enabled == enable: enable = None if access_mode is not None and user.local_rest_api_access_mode == access_mode: access_mode = None if enable is not None or access_mode: await self.request( URL("config/user"), method=hdrs.METH_PATCH, data=PeblarLocalRestApiAccess(enabled=enable, access_mode=access_mode), ) if enable is not None: user.local_rest_api_enabled = enable if not user.local_rest_api_enabled: msg = "The local REST API is not enabled for this device." raise PeblarError(msg) return PeblarApi(host=self.host, token=await self.api_token()) async def modbus_api( self, *, enable: bool | None = None, access_mode: AccessMode | None = None, ) -> None: """Control access to the Modbus API.""" user = await self.user_configuration() if not user.modbus_server_allowed: msg = "The use of the Modbus API is not allowed for this device." raise PeblarError(msg) if user.modbus_server_enabled == enable: enable = None if user.modbus_server_access_mode == access_mode: access_mode = None if enable is not None or access_mode: await self.request( URL("config/user"), method=hdrs.METH_PATCH, data=PeblarModbusApiAccess(enabled=enable, access_mode=access_mode), ) async def api_token(self, *, generate_new_api_token: bool = False) -> str: """Get the API token.""" url = URL("config/api-token") if generate_new_api_token: await self.request(url, method=hdrs.METH_POST) result = await self.request(url) return PeblarApiToken.from_json(result).api_token async def available_versions(self) -> PeblarVersions: """Get available versions.""" result = await self.request( URL("system/software/automatic-update/available-versions") ) return PeblarVersions.from_json(result) async def current_versions(self) -> PeblarVersions: """Get current versions.""" result = await self.request( URL("system/software/automatic-update/current-versions") ) return PeblarVersions.from_json(result) async def smart_charging(self, smart_charging_mode: SmartChargingMode) -> None: """Enable or disable smart charging.""" await self.request( URL("config/user"), method=hdrs.METH_PATCH, data=PeblarSmartCharging(smart_charging=smart_charging_mode), ) async def identify(self) -> None: """Identify the Peblar charger.""" await self.request(URL("system/identify"), method=hdrs.METH_PUT) async def reboot(self) -> None: """Reboot the Peblar charger.""" await self.request( URL("system/reboot"), method=hdrs.METH_POST, data=PeblarReboot(), ) async def update(self, *, package_type: PackageType) -> None: """Update the Peblar charger to the latest version.""" await self.request( URL("system/software/automatic-update/update"), method=hdrs.METH_POST, data=PeblarUpdate(package_type=package_type), ) async def system_information(self) -> PeblarSystemInformation: """Get information about the Peblar charger.""" result = await self.request(URL("system/info")) return PeblarSystemInformation.from_json(result) async def user_configuration(self) -> PeblarUserConfiguration: """Get information about the user configuration.""" result = await self.request(URL("config/user")) return PeblarUserConfiguration.from_json(result) async def close(self) -> None: """Close open client session.""" if self.session and self._close_session: await self.session.close() async def __aenter__(self) -> Self: """Async enter. Returns ------- The Peblar object. """ return self async def __aexit__(self, *_exc_info: object) -> None: """Async exit. Args: ---- _exc_info: Exec type. """ await self.close() @dataclass(kw_only=True) class PeblarApi: """Main class for handling connections with the Local Peblar REST API.""" host: str token: str request_timeout: float = 8 session: ClientSession | None = None _close_session: bool = False def __post_init__(self) -> None: """Initialize the Peblar object.""" self.url = URL.build(scheme="http", host=self.host, path="/api/wlac/v1/") @backoff.on_exception( backoff.expo, PeblarConnectionError, max_tries=3, logger=None, ) async def request( self, uri: URL, *, method: str = hdrs.METH_GET, data: BaseModel | None = None, ) -> str: """Handle a request to a Peblar charger Local REST API.""" if self.session is None: self.session = ClientSession( json_serialize=orjson.dumps, # type: ignore[arg-type] ) self._close_session = True try: async with asyncio.timeout(self.request_timeout): response = await self.session.request( method=method, url=self.url.join(uri), headers={ "Content-Type": "application/json", "Authorization": self.token, }, data=data.to_json() if data else None, ) response.raise_for_status() except TimeoutError as exception: msg = "Timeout occurred while connecting to the Peblar charger API" raise PeblarConnectionTimeoutError(msg) from exception except ClientResponseError as exception: if exception.status == 401: msg = "Authentication error. Provided password is invalid." raise PeblarAuthenticationError(msg) from exception msg = "Error occurred while communicating to the Peblar charger API" raise PeblarError(msg) from exception except ( ClientError, socket.gaierror, ) as exception: msg = "Error occurred while communicating to the Peblar charger API" raise PeblarConnectionError(msg) from exception return await response.text() async def ev_interface( self, *, charge_current_limit: int | None = None, force_single_phase: bool | None = None, ) -> PeblarEVInterface: """Get information about the EV interface.""" url = URL("evinterface") if charge_current_limit is not None or force_single_phase is not None: await self.request( url, method=hdrs.METH_PATCH, data=PeblarEVInterfaceChange( charge_current_limit=charge_current_limit, force_single_phase=force_single_phase, ), ) result = await self.request(url) return PeblarEVInterface.from_json(result) async def health(self) -> PeblarHealth: """Get health information from the Peblar API.""" result = await self.request(URL("health")) return PeblarHealth.from_json(result) async def meter(self) -> PeblarMeter: """Get meter information from the Peblar API.""" result = await self.request(URL("meter")) return PeblarMeter.from_json(result) async def system(self) -> PeblarSystem: """Get system information from the Peblar API.""" result = await self.request(URL("system")) return PeblarSystem.from_json(result) async def close(self) -> None: """Close open client session.""" if self.session and self._close_session: await self.session.close() async def __aenter__(self) -> Self: """Async enter. Returns ------- The PeblarApi object. """ return self async def __aexit__(self, *_exc_info: object) -> None: """Async exit. Args: ---- _exc_info: Exec type. """ await self.close() frenck-python-peblar-e4c64a5/src/peblar/py.typed000066400000000000000000000000001474441165200217120ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/src/peblar/utils.py000066400000000000000000000004371474441165200217430ustar00rootroot00000000000000"""Asynchronous Python client for Peblar EV chargers.""" from functools import lru_cache from awesomeversion import AwesomeVersion @lru_cache def get_awesome_version(version: str) -> AwesomeVersion: """Return a cached AwesomeVersion object.""" return AwesomeVersion(version) frenck-python-peblar-e4c64a5/tests/000077500000000000000000000000001474441165200173335ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/tests/__init__.py000066400000000000000000000003541474441165200214460ustar00rootroot00000000000000"""Asynchronous Python client for Peblar EV chargers.""" from pathlib import Path def load_fixture(filename: str) -> str: """Load a fixture.""" path = Path(__file__).parent / "fixtures" / filename return path.read_text() frenck-python-peblar-e4c64a5/tests/fixtures/000077500000000000000000000000001474441165200212045ustar00rootroot00000000000000frenck-python-peblar-e4c64a5/tests/fixtures/device_status_closed.json000066400000000000000000000006761474441165200263030ustar00rootroot00000000000000{ "result": "OK", "product": "iQ3", "dev_id": "_3c_e9_e_6d_21_84_", "proto_ver": "0.1", "door_num": 2, "night_mode_en": 0, "fw_ver": "10.10", "led_brightness": 100, "data": { "door1": { "index": 0, "status": "close", "lockup": 0, "disabled": 0 }, "door2": { "index": 1, "status": "close", "lockup": 0, "disabled": 0 } } } frenck-python-peblar-e4c64a5/tests/fixtures/device_status_disabled.json000066400000000000000000000006751474441165200266000ustar00rootroot00000000000000{ "result": "OK", "product": "iQ3", "dev_id": "_3c_e9_e_6d_21_84_", "proto_ver": "0.1", "door_num": 2, "night_mode_en": 0, "fw_ver": "10.10", "led_brightness": 100, "data": { "door1": { "index": 0, "status": "close", "lockup": 0, "disabled": 1 }, "door2": { "index": 1, "status": "open", "lockup": 0, "disabled": 1 } } } frenck-python-peblar-e4c64a5/tests/fixtures/device_status_locked_out.json000066400000000000000000000006751474441165200271610ustar00rootroot00000000000000{ "result": "OK", "product": "iQ3", "dev_id": "_3c_e9_e_6d_21_84_", "proto_ver": "0.1", "door_num": 2, "night_mode_en": 0, "fw_ver": "10.10", "led_brightness": 100, "data": { "door1": { "index": 0, "status": "close", "lockup": 1, "disabled": 0 }, "door2": { "index": 1, "status": "open", "lockup": 1, "disabled": 0 } } } frenck-python-peblar-e4c64a5/tests/fixtures/device_status_open.json000066400000000000000000000006741474441165200257710ustar00rootroot00000000000000{ "result": "OK", "product": "iQ3", "dev_id": "_3c_e9_e_6d_21_84_", "proto_ver": "0.1", "door_num": 2, "night_mode_en": 0, "fw_ver": "10.10", "led_brightness": 100, "data": { "door1": { "index": 0, "status": "open", "lockup": 0, "disabled": 0 }, "door2": { "index": 1, "status": "open", "lockup": 0, "disabled": 0 } } } frenck-python-peblar-e4c64a5/tests/fixtures/device_status_unsupported.json000066400000000000000000000010021474441165200274020ustar00rootroot00000000000000{ "result": "OK", "product": "iQ3", "dev_id": "_3c_e9_e_6d_21_84_", "proto_ver": "0.1", "night_mode_en": 0, "fw_ver": "9.97", "data": { "door1": { "index": 0, "status": "open", "lockup": 0, "disabled": 0 }, "door2": { "index": 1, "status": "open", "lockup": 0, "disabled": 0 }, "door3": { "index": 2, "status": "open", "lockup": 0, "disabled": 0 } } } frenck-python-peblar-e4c64a5/tests/fixtures/fail_response.json000066400000000000000000000000531474441165200247260ustar00rootroot00000000000000{"result": "Fail", "Info": "OMG Puppies!"} frenck-python-peblar-e4c64a5/tests/fixtures/ok_response.json000066400000000000000000000000211474441165200244170ustar00rootroot00000000000000{"result": "OK"} frenck-python-peblar-e4c64a5/tests/fixtures/token_fail.json000066400000000000000000000000311474441165200242040ustar00rootroot00000000000000{"result": "token fail"} frenck-python-peblar-e4c64a5/tests/ruff.toml000066400000000000000000000006311474441165200211720ustar00rootroot00000000000000# This extend our general Ruff rules specifically for tests extend = "../pyproject.toml" lint.extend-select = [ "PT", # Use @pytest.fixture without parentheses ] lint.extend-ignore = [ "S101", # Use of assert detected. As these are tests... "S106", # Yes, we pass in a dummy token in tests... "SLF001", # Tests will access private/protected members... "TC002", # pytest doesn't like this one... ] frenck-python-peblar-e4c64a5/tests/test_peblar.py000066400000000000000000000040731474441165200222150ustar00rootroot00000000000000"""Asynchronous Python client for Peblar EV chargers.""" from __future__ import annotations import pytest from aiohttp import ClientResponse, ClientSession from aresponses import Response, ResponsesMockServer from peblar import Peblar from peblar.exceptions import ( PeblarAuthenticationError, PeblarError, ) async def test_identify(aresponses: ResponsesMockServer) -> None: """Test the identify method.""" async def response_handler(request: ClientResponse) -> Response: """Response handler for this test.""" assert not await request.text() return aresponses.Response(status=200) aresponses.add( "example.com", "/api/v1/system/identify", "PUT", response_handler, ) async with Peblar(host="example.com") as peblar: await peblar.identify() async def test_request_with_shared_session(aresponses: ResponsesMockServer) -> None: """Test a passed in shared session works as expected.""" aresponses.add( "example.com", "/api/v1/system/identify", "PUT", aresponses.Response(status=200), ) async with ClientSession() as session: peblar = Peblar(host="example.com", session=session) await peblar.identify() await peblar.close() async def test_http_error400(aresponses: ResponsesMockServer) -> None: """Test HTTP 404 response handling.""" aresponses.add( "example.com", "/api/v1/system/identify", "PUT", aresponses.Response(text="OMG PUPPIES!", status=400), ) async with Peblar(host="example.com") as peblar: with pytest.raises(PeblarError): await peblar.identify() async def test_unauthenticated_response(aresponses: ResponsesMockServer) -> None: """Test authentication failure.""" aresponses.add( "example.com", "/api/v1/system/identify", "PUT", aresponses.Response(status=401), ) async with Peblar(host="example.com") as peblar: with pytest.raises(PeblarAuthenticationError): await peblar.identify() frenck-python-peblar-e4c64a5/uv.lock000066400000000000000000005105051474441165200175030ustar00rootroot00000000000000version = 1 requires-python = ">=3.11" resolution-markers = [ "python_full_version >= '3.12'", "python_full_version < '3.12'", ] [options] prerelease-mode = "allow" [[package]] name = "aiohappyeyeballs" version = "2.4.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7f/55/e4373e888fdacb15563ef6fa9fa8c8252476ea071e96fb46defac9f18bf2/aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745", size = 21977 } wheels = [ { url = "https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8", size = 14756 }, ] [[package]] name = "aiohttp" version = "3.11.11" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohappyeyeballs" }, { name = "aiosignal" }, { name = "attrs" }, { name = "frozenlist" }, { name = "multidict" }, { name = "propcache" }, { name = "yarl" }, ] sdist = { url = "https://files.pythonhosted.org/packages/fe/ed/f26db39d29cd3cb2f5a3374304c713fe5ab5a0e4c8ee25a0c45cc6adf844/aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e", size = 7669618 } wheels = [ { url = "https://files.pythonhosted.org/packages/34/ae/e8806a9f054e15f1d18b04db75c23ec38ec954a10c0a68d3bd275d7e8be3/aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76", size = 708624 }, { url = "https://files.pythonhosted.org/packages/c7/e0/313ef1a333fb4d58d0c55a6acb3cd772f5d7756604b455181049e222c020/aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538", size = 468507 }, { url = "https://files.pythonhosted.org/packages/a9/60/03455476bf1f467e5b4a32a465c450548b2ce724eec39d69f737191f936a/aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204", size = 455571 }, { url = "https://files.pythonhosted.org/packages/be/f9/469588603bd75bf02c8ffb8c8a0d4b217eed446b49d4a767684685aa33fd/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9", size = 1685694 }, { url = "https://files.pythonhosted.org/packages/88/b9/1b7fa43faf6c8616fa94c568dc1309ffee2b6b68b04ac268e5d64b738688/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03", size = 1743660 }, { url = "https://files.pythonhosted.org/packages/2a/8b/0248d19dbb16b67222e75f6aecedd014656225733157e5afaf6a6a07e2e8/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287", size = 1785421 }, { url = "https://files.pythonhosted.org/packages/c4/11/f478e071815a46ca0a5ae974651ff0c7a35898c55063305a896e58aa1247/aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e", size = 1675145 }, { url = "https://files.pythonhosted.org/packages/26/5d/284d182fecbb5075ae10153ff7374f57314c93a8681666600e3a9e09c505/aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665", size = 1619804 }, { url = "https://files.pythonhosted.org/packages/1b/78/980064c2ad685c64ce0e8aeeb7ef1e53f43c5b005edcd7d32e60809c4992/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b", size = 1654007 }, { url = "https://files.pythonhosted.org/packages/21/8d/9e658d63b1438ad42b96f94da227f2e2c1d5c6001c9e8ffcc0bfb22e9105/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34", size = 1650022 }, { url = "https://files.pythonhosted.org/packages/85/fd/a032bf7f2755c2df4f87f9effa34ccc1ef5cea465377dbaeef93bb56bbd6/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d", size = 1732899 }, { url = "https://files.pythonhosted.org/packages/c5/0c/c2b85fde167dd440c7ba50af2aac20b5a5666392b174df54c00f888c5a75/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2", size = 1755142 }, { url = "https://files.pythonhosted.org/packages/bc/78/91ae1a3b3b3bed8b893c5d69c07023e151b1c95d79544ad04cf68f596c2f/aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773", size = 1692736 }, { url = "https://files.pythonhosted.org/packages/77/89/a7ef9c4b4cdb546fcc650ca7f7395aaffbd267f0e1f648a436bec33c9b95/aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62", size = 416418 }, { url = "https://files.pythonhosted.org/packages/fc/db/2192489a8a51b52e06627506f8ac8df69ee221de88ab9bdea77aa793aa6a/aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac", size = 442509 }, { url = "https://files.pythonhosted.org/packages/69/cf/4bda538c502f9738d6b95ada11603c05ec260807246e15e869fc3ec5de97/aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886", size = 704666 }, { url = "https://files.pythonhosted.org/packages/46/7b/87fcef2cad2fad420ca77bef981e815df6904047d0a1bd6aeded1b0d1d66/aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2", size = 464057 }, { url = "https://files.pythonhosted.org/packages/5a/a6/789e1f17a1b6f4a38939fbc39d29e1d960d5f89f73d0629a939410171bc0/aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c", size = 455996 }, { url = "https://files.pythonhosted.org/packages/b7/dd/485061fbfef33165ce7320db36e530cd7116ee1098e9c3774d15a732b3fd/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a", size = 1682367 }, { url = "https://files.pythonhosted.org/packages/e9/d7/9ec5b3ea9ae215c311d88b2093e8da17e67b8856673e4166c994e117ee3e/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231", size = 1736989 }, { url = "https://files.pythonhosted.org/packages/d6/fb/ea94927f7bfe1d86178c9d3e0a8c54f651a0a655214cce930b3c679b8f64/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e", size = 1793265 }, { url = "https://files.pythonhosted.org/packages/40/7f/6de218084f9b653026bd7063cd8045123a7ba90c25176465f266976d8c82/aiohttp-3.11.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8", size = 1691841 }, { url = "https://files.pythonhosted.org/packages/77/e2/992f43d87831cbddb6b09c57ab55499332f60ad6fdbf438ff4419c2925fc/aiohttp-3.11.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8", size = 1619317 }, { url = "https://files.pythonhosted.org/packages/96/74/879b23cdd816db4133325a201287c95bef4ce669acde37f8f1b8669e1755/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c", size = 1641416 }, { url = "https://files.pythonhosted.org/packages/30/98/b123f6b15d87c54e58fd7ae3558ff594f898d7f30a90899718f3215ad328/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab", size = 1646514 }, { url = "https://files.pythonhosted.org/packages/d7/38/257fda3dc99d6978ab943141d5165ec74fd4b4164baa15e9c66fa21da86b/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da", size = 1702095 }, { url = "https://files.pythonhosted.org/packages/0c/f4/ddab089053f9fb96654df5505c0a69bde093214b3c3454f6bfdb1845f558/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853", size = 1734611 }, { url = "https://files.pythonhosted.org/packages/c3/d6/f30b2bc520c38c8aa4657ed953186e535ae84abe55c08d0f70acd72ff577/aiohttp-3.11.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e", size = 1694576 }, { url = "https://files.pythonhosted.org/packages/bc/97/b0a88c3f4c6d0020b34045ee6d954058abc870814f6e310c4c9b74254116/aiohttp-3.11.11-cp312-cp312-win32.whl", hash = "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600", size = 411363 }, { url = "https://files.pythonhosted.org/packages/7f/23/cc36d9c398980acaeeb443100f0216f50a7cfe20c67a9fd0a2f1a5a846de/aiohttp-3.11.11-cp312-cp312-win_amd64.whl", hash = "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d", size = 437666 }, { url = "https://files.pythonhosted.org/packages/49/d1/d8af164f400bad432b63e1ac857d74a09311a8334b0481f2f64b158b50eb/aiohttp-3.11.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9", size = 697982 }, { url = "https://files.pythonhosted.org/packages/92/d1/faad3bf9fa4bfd26b95c69fc2e98937d52b1ff44f7e28131855a98d23a17/aiohttp-3.11.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194", size = 460662 }, { url = "https://files.pythonhosted.org/packages/db/61/0d71cc66d63909dabc4590f74eba71f91873a77ea52424401c2498d47536/aiohttp-3.11.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f", size = 452950 }, { url = "https://files.pythonhosted.org/packages/07/db/6d04bc7fd92784900704e16b745484ef45b77bd04e25f58f6febaadf7983/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104", size = 1665178 }, { url = "https://files.pythonhosted.org/packages/54/5c/e95ade9ae29f375411884d9fd98e50535bf9fe316c9feb0f30cd2ac8f508/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff", size = 1717939 }, { url = "https://files.pythonhosted.org/packages/6f/1c/1e7d5c5daea9e409ed70f7986001b8c9e3a49a50b28404498d30860edab6/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3", size = 1775125 }, { url = "https://files.pythonhosted.org/packages/5d/66/890987e44f7d2f33a130e37e01a164168e6aff06fce15217b6eaf14df4f6/aiohttp-3.11.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1", size = 1677176 }, { url = "https://files.pythonhosted.org/packages/8f/dc/e2ba57d7a52df6cdf1072fd5fa9c6301a68e1cd67415f189805d3eeb031d/aiohttp-3.11.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4", size = 1603192 }, { url = "https://files.pythonhosted.org/packages/6c/9e/8d08a57de79ca3a358da449405555e668f2c8871a7777ecd2f0e3912c272/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d", size = 1618296 }, { url = "https://files.pythonhosted.org/packages/56/51/89822e3ec72db352c32e7fc1c690370e24e231837d9abd056490f3a49886/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87", size = 1616524 }, { url = "https://files.pythonhosted.org/packages/2c/fa/e2e6d9398f462ffaa095e84717c1732916a57f1814502929ed67dd7568ef/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2", size = 1685471 }, { url = "https://files.pythonhosted.org/packages/ae/5f/6bb976e619ca28a052e2c0ca7b0251ccd893f93d7c24a96abea38e332bf6/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12", size = 1715312 }, { url = "https://files.pythonhosted.org/packages/79/c1/756a7e65aa087c7fac724d6c4c038f2faaa2a42fe56dbc1dd62a33ca7213/aiohttp-3.11.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5", size = 1672783 }, { url = "https://files.pythonhosted.org/packages/73/ba/a6190ebb02176c7f75e6308da31f5d49f6477b651a3dcfaaaca865a298e2/aiohttp-3.11.11-cp313-cp313-win32.whl", hash = "sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d", size = 410229 }, { url = "https://files.pythonhosted.org/packages/b8/62/c9fa5bafe03186a0e4699150a7fed9b1e73240996d0d2f0e5f70f3fdf471/aiohttp-3.11.11-cp313-cp313-win_amd64.whl", hash = "sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99", size = 436081 }, ] [[package]] name = "aiosignal" version = "1.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "frozenlist" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ba/b5/6d55e80f6d8a08ce22b982eafa278d823b541c925f11ee774b0b9c43473d/aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54", size = 19424 } wheels = [ { url = "https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5", size = 7597 }, ] [[package]] name = "aresponses" version = "3.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, { name = "pytest-asyncio" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ed/96/99b3f8c2ad6a5547bcb4726e572513564c23d4a3a3e21a03038dd3a84fe4/aresponses-3.0.0.tar.gz", hash = "sha256:8731d0609fe4c954e21f17753dc868dca9e2e002b020a33dc9212004599b11e7", size = 14796 } wheels = [ { url = "https://files.pythonhosted.org/packages/00/e6/554d29eb029da3b0ce3642483fce758043f3132b94ab54ecd1053eee29ee/aresponses-3.0.0-py3-none-any.whl", hash = "sha256:8093ab4758eb4aba91c765a50295b269ecfc0a9e7c7158954760bc0c23503970", size = 9879 }, ] [[package]] name = "astroid" version = "3.3.8" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/80/c5/5c83c48bbf547f3dd8b587529db7cf5a265a3368b33e85e76af8ff6061d3/astroid-3.3.8.tar.gz", hash = "sha256:a88c7994f914a4ea8572fac479459f4955eeccc877be3f2d959a33273b0cf40b", size = 398196 } wheels = [ { url = "https://files.pythonhosted.org/packages/07/28/0bc8a17d6cd4cc3c79ae41b7105a2b9a327c110e5ddd37a8a27b29a5c8a2/astroid-3.3.8-py3-none-any.whl", hash = "sha256:187ccc0c248bfbba564826c26f070494f7bc964fd286b6d9fff4420e55de828c", size = 275153 }, ] [[package]] name = "attrs" version = "24.3.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/48/c8/6260f8ccc11f0917360fc0da435c5c9c7504e3db174d5a12a1494887b045/attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff", size = 805984 } wheels = [ { url = "https://files.pythonhosted.org/packages/89/aa/ab0f7891a01eeb2d2e338ae8fecbe57fcebea1a24dbb64d45801bfab481d/attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308", size = 63397 }, ] [[package]] name = "awesomeversion" version = "24.6.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9d/e9/1baaf8619a3d66b467ba105976897e67b36dbad93b619753768357dbd475/awesomeversion-24.6.0.tar.gz", hash = "sha256:aee7ccbaed6f8d84e0f0364080c7734a0166d77ea6ccfcc4900b38917f1efc71", size = 11997 } wheels = [ { url = "https://files.pythonhosted.org/packages/81/a5/258ffce7048e8be24c6f402bcbf5d1b3933d5d63421d000a55e74248481b/awesomeversion-24.6.0-py3-none-any.whl", hash = "sha256:6768415b8954b379a25cebf21ed4f682cab10aebf3f82a6640aaaa15ec6821f2", size = 14716 }, ] [[package]] name = "backoff" version = "2.2.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/47/d7/5bbeb12c44d7c4f2fb5b56abce497eb5ed9f34d85701de869acedd602619/backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba", size = 17001 } wheels = [ { url = "https://files.pythonhosted.org/packages/df/73/b6e24bd22e6720ca8ee9a85a0c4a2971af8497d8f3193fa05390cbd46e09/backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8", size = 15148 }, ] [[package]] name = "cfgv" version = "3.4.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114 } wheels = [ { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249 }, ] [[package]] name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, ] [[package]] name = "codespell" version = "2.4.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b0/2f/706691245790ae6c63252d48b7ff5e3635951d55b3ce3c0ac13d898bf70b/codespell-2.4.0.tar.gz", hash = "sha256:587d45b14707fb8ce51339ba4cce50ae0e98ce228ef61f3c5e160e34f681be58", size = 344743 } wheels = [ { url = "https://files.pythonhosted.org/packages/19/ce/39bfb82aa428a3ac4d94cc8c9faa3eadeadb2606eee3b584f68d9b575b43/codespell-2.4.0-py3-none-any.whl", hash = "sha256:b4c5b779f747dd481587aeecb5773301183f52b94b96ed51a28126d0482eec1d", size = 344508 }, ] [[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 } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, ] [[package]] name = "covdefaults" version = "2.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage" }, ] sdist = { url = "https://files.pythonhosted.org/packages/44/ee/9a6f2611f72e4c5657ae5542a510cf4164d2c673687c0ea73bb1cbd85b4d/covdefaults-2.3.0.tar.gz", hash = "sha256:4e99f679f12d792bc62e5510fa3eb59546ed47bd569e36e4fddc4081c9c3ebf7", size = 4835 } wheels = [ { url = "https://files.pythonhosted.org/packages/76/4c/823bc951445aa97e5a1b7e337690db3abf85212c8d138e170922e7916ac8/covdefaults-2.3.0-py2.py3-none-any.whl", hash = "sha256:2832961f6ffcfe4b57c338bc3418a3526f495c26fb9c54565409c5532f7c41be", size = 5144 }, ] [[package]] name = "coverage" version = "7.6.10" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/84/ba/ac14d281f80aab516275012e8875991bb06203957aa1e19950139238d658/coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23", size = 803868 } wheels = [ { url = "https://files.pythonhosted.org/packages/85/d2/5e175fcf6766cf7501a8541d81778fd2f52f4870100e791f5327fd23270b/coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3", size = 208088 }, { url = "https://files.pythonhosted.org/packages/4b/6f/06db4dc8fca33c13b673986e20e466fd936235a6ec1f0045c3853ac1b593/coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43", size = 208536 }, { url = "https://files.pythonhosted.org/packages/0d/62/c6a0cf80318c1c1af376d52df444da3608eafc913b82c84a4600d8349472/coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132", size = 240474 }, { url = "https://files.pythonhosted.org/packages/a3/59/750adafc2e57786d2e8739a46b680d4fb0fbc2d57fbcb161290a9f1ecf23/coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f", size = 237880 }, { url = "https://files.pythonhosted.org/packages/2c/f8/ef009b3b98e9f7033c19deb40d629354aab1d8b2d7f9cfec284dbedf5096/coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994", size = 239750 }, { url = "https://files.pythonhosted.org/packages/a6/e2/6622f3b70f5f5b59f705e680dae6db64421af05a5d1e389afd24dae62e5b/coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99", size = 238642 }, { url = "https://files.pythonhosted.org/packages/2d/10/57ac3f191a3c95c67844099514ff44e6e19b2915cd1c22269fb27f9b17b6/coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd", size = 237266 }, { url = "https://files.pythonhosted.org/packages/ee/2d/7016f4ad9d553cabcb7333ed78ff9d27248ec4eba8dd21fa488254dff894/coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377", size = 238045 }, { url = "https://files.pythonhosted.org/packages/a7/fe/45af5c82389a71e0cae4546413266d2195c3744849669b0bab4b5f2c75da/coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8", size = 210647 }, { url = "https://files.pythonhosted.org/packages/db/11/3f8e803a43b79bc534c6a506674da9d614e990e37118b4506faf70d46ed6/coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609", size = 211508 }, { url = "https://files.pythonhosted.org/packages/86/77/19d09ea06f92fdf0487499283b1b7af06bc422ea94534c8fe3a4cd023641/coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853", size = 208281 }, { url = "https://files.pythonhosted.org/packages/b6/67/5479b9f2f99fcfb49c0d5cf61912a5255ef80b6e80a3cddba39c38146cf4/coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078", size = 208514 }, { url = "https://files.pythonhosted.org/packages/15/d1/febf59030ce1c83b7331c3546d7317e5120c5966471727aa7ac157729c4b/coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0", size = 241537 }, { url = "https://files.pythonhosted.org/packages/4b/7e/5ac4c90192130e7cf8b63153fe620c8bfd9068f89a6d9b5f26f1550f7a26/coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50", size = 238572 }, { url = "https://files.pythonhosted.org/packages/dc/03/0334a79b26ecf59958f2fe9dd1f5ab3e2f88db876f5071933de39af09647/coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022", size = 240639 }, { url = "https://files.pythonhosted.org/packages/d7/45/8a707f23c202208d7b286d78ad6233f50dcf929319b664b6cc18a03c1aae/coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b", size = 240072 }, { url = "https://files.pythonhosted.org/packages/66/02/603ce0ac2d02bc7b393279ef618940b4a0535b0868ee791140bda9ecfa40/coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0", size = 238386 }, { url = "https://files.pythonhosted.org/packages/04/62/4e6887e9be060f5d18f1dd58c2838b2d9646faf353232dec4e2d4b1c8644/coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852", size = 240054 }, { url = "https://files.pythonhosted.org/packages/5c/74/83ae4151c170d8bd071924f212add22a0e62a7fe2b149edf016aeecad17c/coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359", size = 210904 }, { url = "https://files.pythonhosted.org/packages/c3/54/de0893186a221478f5880283119fc40483bc460b27c4c71d1b8bba3474b9/coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247", size = 211692 }, { url = "https://files.pythonhosted.org/packages/25/6d/31883d78865529257bf847df5789e2ae80e99de8a460c3453dbfbe0db069/coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9", size = 208308 }, { url = "https://files.pythonhosted.org/packages/70/22/3f2b129cc08de00c83b0ad6252e034320946abfc3e4235c009e57cfeee05/coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b", size = 208565 }, { url = "https://files.pythonhosted.org/packages/97/0a/d89bc2d1cc61d3a8dfe9e9d75217b2be85f6c73ebf1b9e3c2f4e797f4531/coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690", size = 241083 }, { url = "https://files.pythonhosted.org/packages/4c/81/6d64b88a00c7a7aaed3a657b8eaa0931f37a6395fcef61e53ff742b49c97/coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18", size = 238235 }, { url = "https://files.pythonhosted.org/packages/9a/0b/7797d4193f5adb4b837207ed87fecf5fc38f7cc612b369a8e8e12d9fa114/coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c", size = 240220 }, { url = "https://files.pythonhosted.org/packages/65/4d/6f83ca1bddcf8e51bf8ff71572f39a1c73c34cf50e752a952c34f24d0a60/coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd", size = 239847 }, { url = "https://files.pythonhosted.org/packages/30/9d/2470df6aa146aff4c65fee0f87f58d2164a67533c771c9cc12ffcdb865d5/coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e", size = 237922 }, { url = "https://files.pythonhosted.org/packages/08/dd/723fef5d901e6a89f2507094db66c091449c8ba03272861eaefa773ad95c/coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694", size = 239783 }, { url = "https://files.pythonhosted.org/packages/3d/f7/64d3298b2baf261cb35466000628706ce20a82d42faf9b771af447cd2b76/coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6", size = 210965 }, { url = "https://files.pythonhosted.org/packages/d5/58/ec43499a7fc681212fe7742fe90b2bc361cdb72e3181ace1604247a5b24d/coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e", size = 211719 }, { url = "https://files.pythonhosted.org/packages/ab/c9/f2857a135bcff4330c1e90e7d03446b036b2363d4ad37eb5e3a47bbac8a6/coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe", size = 209050 }, { url = "https://files.pythonhosted.org/packages/aa/b3/f840e5bd777d8433caa9e4a1eb20503495709f697341ac1a8ee6a3c906ad/coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273", size = 209321 }, { url = "https://files.pythonhosted.org/packages/85/7d/125a5362180fcc1c03d91850fc020f3831d5cda09319522bcfa6b2b70be7/coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8", size = 252039 }, { url = "https://files.pythonhosted.org/packages/a9/9c/4358bf3c74baf1f9bddd2baf3756b54c07f2cfd2535f0a47f1e7757e54b3/coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098", size = 247758 }, { url = "https://files.pythonhosted.org/packages/cf/c7/de3eb6fc5263b26fab5cda3de7a0f80e317597a4bad4781859f72885f300/coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb", size = 250119 }, { url = "https://files.pythonhosted.org/packages/3e/e6/43de91f8ba2ec9140c6a4af1102141712949903dc732cf739167cfa7a3bc/coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0", size = 249597 }, { url = "https://files.pythonhosted.org/packages/08/40/61158b5499aa2adf9e37bc6d0117e8f6788625b283d51e7e0c53cf340530/coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf", size = 247473 }, { url = "https://files.pythonhosted.org/packages/50/69/b3f2416725621e9f112e74e8470793d5b5995f146f596f133678a633b77e/coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2", size = 248737 }, { url = "https://files.pythonhosted.org/packages/3c/6e/fe899fb937657db6df31cc3e61c6968cb56d36d7326361847440a430152e/coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312", size = 211611 }, { url = "https://files.pythonhosted.org/packages/1c/55/52f5e66142a9d7bc93a15192eba7a78513d2abf6b3558d77b4ca32f5f424/coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d", size = 212781 }, ] [package.optional-dependencies] toml = [ { name = "tomli", marker = "python_full_version <= '3.11'" }, ] [[package]] name = "dill" version = "0.3.9" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/70/43/86fe3f9e130c4137b0f1b50784dd70a5087b911fe07fa81e53e0c4c47fea/dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c", size = 187000 } wheels = [ { url = "https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a", size = 119418 }, ] [[package]] name = "distlib" version = "0.3.9" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923 } wheels = [ { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973 }, ] [[package]] name = "filelock" version = "3.16.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/9d/db/3ef5bb276dae18d6ec2124224403d1d67bccdbefc17af4cc8f553e341ab1/filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435", size = 18037 } wheels = [ { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163 }, ] [[package]] name = "frozenlist" version = "1.5.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/8f/ed/0f4cec13a93c02c47ec32d81d11c0c1efbadf4a471e3f3ce7cad366cbbd3/frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", size = 39930 } wheels = [ { url = "https://files.pythonhosted.org/packages/79/43/0bed28bf5eb1c9e4301003b74453b8e7aa85fb293b31dde352aac528dafc/frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30", size = 94987 }, { url = "https://files.pythonhosted.org/packages/bb/bf/b74e38f09a246e8abbe1e90eb65787ed745ccab6eaa58b9c9308e052323d/frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5", size = 54584 }, { url = "https://files.pythonhosted.org/packages/2c/31/ab01375682f14f7613a1ade30149f684c84f9b8823a4391ed950c8285656/frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778", size = 52499 }, { url = "https://files.pythonhosted.org/packages/98/a8/d0ac0b9276e1404f58fec3ab6e90a4f76b778a49373ccaf6a563f100dfbc/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a", size = 276357 }, { url = "https://files.pythonhosted.org/packages/ad/c9/c7761084fa822f07dac38ac29f841d4587570dd211e2262544aa0b791d21/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869", size = 287516 }, { url = "https://files.pythonhosted.org/packages/a1/ff/cd7479e703c39df7bdab431798cef89dc75010d8aa0ca2514c5b9321db27/frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d", size = 283131 }, { url = "https://files.pythonhosted.org/packages/59/a0/370941beb47d237eca4fbf27e4e91389fd68699e6f4b0ebcc95da463835b/frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45", size = 261320 }, { url = "https://files.pythonhosted.org/packages/b8/5f/c10123e8d64867bc9b4f2f510a32042a306ff5fcd7e2e09e5ae5100ee333/frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d", size = 274877 }, { url = "https://files.pythonhosted.org/packages/fa/79/38c505601ae29d4348f21706c5d89755ceded02a745016ba2f58bd5f1ea6/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3", size = 269592 }, { url = "https://files.pythonhosted.org/packages/19/e2/39f3a53191b8204ba9f0bb574b926b73dd2efba2a2b9d2d730517e8f7622/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a", size = 265934 }, { url = "https://files.pythonhosted.org/packages/d5/c9/3075eb7f7f3a91f1a6b00284af4de0a65a9ae47084930916f5528144c9dd/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9", size = 283859 }, { url = "https://files.pythonhosted.org/packages/05/f5/549f44d314c29408b962fa2b0e69a1a67c59379fb143b92a0a065ffd1f0f/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2", size = 287560 }, { url = "https://files.pythonhosted.org/packages/9d/f8/cb09b3c24a3eac02c4c07a9558e11e9e244fb02bf62c85ac2106d1eb0c0b/frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf", size = 277150 }, { url = "https://files.pythonhosted.org/packages/37/48/38c2db3f54d1501e692d6fe058f45b6ad1b358d82cd19436efab80cfc965/frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942", size = 45244 }, { url = "https://files.pythonhosted.org/packages/ca/8c/2ddffeb8b60a4bce3b196c32fcc30d8830d4615e7b492ec2071da801b8ad/frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d", size = 51634 }, { url = "https://files.pythonhosted.org/packages/79/73/fa6d1a96ab7fd6e6d1c3500700963eab46813847f01ef0ccbaa726181dd5/frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", size = 94026 }, { url = "https://files.pythonhosted.org/packages/ab/04/ea8bf62c8868b8eada363f20ff1b647cf2e93377a7b284d36062d21d81d1/frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", size = 54150 }, { url = "https://files.pythonhosted.org/packages/d0/9a/8e479b482a6f2070b26bda572c5e6889bb3ba48977e81beea35b5ae13ece/frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", size = 51927 }, { url = "https://files.pythonhosted.org/packages/e3/12/2aad87deb08a4e7ccfb33600871bbe8f0e08cb6d8224371387f3303654d7/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a", size = 282647 }, { url = "https://files.pythonhosted.org/packages/77/f2/07f06b05d8a427ea0060a9cef6e63405ea9e0d761846b95ef3fb3be57111/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", size = 289052 }, { url = "https://files.pythonhosted.org/packages/bd/9f/8bf45a2f1cd4aa401acd271b077989c9267ae8463e7c8b1eb0d3f561b65e/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", size = 291719 }, { url = "https://files.pythonhosted.org/packages/41/d1/1f20fd05a6c42d3868709b7604c9f15538a29e4f734c694c6bcfc3d3b935/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", size = 267433 }, { url = "https://files.pythonhosted.org/packages/af/f2/64b73a9bb86f5a89fb55450e97cd5c1f84a862d4ff90d9fd1a73ab0f64a5/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", size = 283591 }, { url = "https://files.pythonhosted.org/packages/29/e2/ffbb1fae55a791fd6c2938dd9ea779509c977435ba3940b9f2e8dc9d5316/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", size = 273249 }, { url = "https://files.pythonhosted.org/packages/2e/6e/008136a30798bb63618a114b9321b5971172a5abddff44a100c7edc5ad4f/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", size = 271075 }, { url = "https://files.pythonhosted.org/packages/ae/f0/4e71e54a026b06724cec9b6c54f0b13a4e9e298cc8db0f82ec70e151f5ce/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", size = 285398 }, { url = "https://files.pythonhosted.org/packages/4d/36/70ec246851478b1c0b59f11ef8ade9c482ff447c1363c2bd5fad45098b12/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", size = 294445 }, { url = "https://files.pythonhosted.org/packages/37/e0/47f87544055b3349b633a03c4d94b405956cf2437f4ab46d0928b74b7526/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", size = 280569 }, { url = "https://files.pythonhosted.org/packages/f9/7c/490133c160fb6b84ed374c266f42800e33b50c3bbab1652764e6e1fc498a/frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", size = 44721 }, { url = "https://files.pythonhosted.org/packages/b1/56/4e45136ffc6bdbfa68c29ca56ef53783ef4c2fd395f7cbf99a2624aa9aaa/frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", size = 51329 }, { url = "https://files.pythonhosted.org/packages/da/3b/915f0bca8a7ea04483622e84a9bd90033bab54bdf485479556c74fd5eaf5/frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953", size = 91538 }, { url = "https://files.pythonhosted.org/packages/c7/d1/a7c98aad7e44afe5306a2b068434a5830f1470675f0e715abb86eb15f15b/frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0", size = 52849 }, { url = "https://files.pythonhosted.org/packages/3a/c8/76f23bf9ab15d5f760eb48701909645f686f9c64fbb8982674c241fbef14/frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2", size = 50583 }, { url = "https://files.pythonhosted.org/packages/1f/22/462a3dd093d11df623179d7754a3b3269de3b42de2808cddef50ee0f4f48/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f", size = 265636 }, { url = "https://files.pythonhosted.org/packages/80/cf/e075e407fc2ae7328155a1cd7e22f932773c8073c1fc78016607d19cc3e5/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608", size = 270214 }, { url = "https://files.pythonhosted.org/packages/a1/58/0642d061d5de779f39c50cbb00df49682832923f3d2ebfb0fedf02d05f7f/frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b", size = 273905 }, { url = "https://files.pythonhosted.org/packages/ab/66/3fe0f5f8f2add5b4ab7aa4e199f767fd3b55da26e3ca4ce2cc36698e50c4/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840", size = 250542 }, { url = "https://files.pythonhosted.org/packages/f6/b8/260791bde9198c87a465224e0e2bb62c4e716f5d198fc3a1dacc4895dbd1/frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439", size = 267026 }, { url = "https://files.pythonhosted.org/packages/2e/a4/3d24f88c527f08f8d44ade24eaee83b2627793fa62fa07cbb7ff7a2f7d42/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de", size = 257690 }, { url = "https://files.pythonhosted.org/packages/de/9a/d311d660420b2beeff3459b6626f2ab4fb236d07afbdac034a4371fe696e/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641", size = 253893 }, { url = "https://files.pythonhosted.org/packages/c6/23/e491aadc25b56eabd0f18c53bb19f3cdc6de30b2129ee0bc39cd387cd560/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e", size = 267006 }, { url = "https://files.pythonhosted.org/packages/08/c4/ab918ce636a35fb974d13d666dcbe03969592aeca6c3ab3835acff01f79c/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9", size = 276157 }, { url = "https://files.pythonhosted.org/packages/c0/29/3b7a0bbbbe5a34833ba26f686aabfe982924adbdcafdc294a7a129c31688/frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03", size = 264642 }, { url = "https://files.pythonhosted.org/packages/ab/42/0595b3dbffc2e82d7fe658c12d5a5bafcd7516c6bf2d1d1feb5387caa9c1/frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c", size = 44914 }, { url = "https://files.pythonhosted.org/packages/17/c4/b7db1206a3fea44bf3b838ca61deb6f74424a8a5db1dd53ecb21da669be6/frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28", size = 51167 }, { url = "https://files.pythonhosted.org/packages/c6/c8/a5be5b7550c10858fcf9b0ea054baccab474da77d37f1e828ce043a3a5d4/frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", size = 11901 }, ] [[package]] name = "identify" version = "2.6.5" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/cf/92/69934b9ef3c31ca2470980423fda3d00f0460ddefdf30a67adf7f17e2e00/identify-2.6.5.tar.gz", hash = "sha256:c10b33f250e5bba374fae86fb57f3adcebf1161bce7cdf92031915fd480c13bc", size = 99213 } wheels = [ { url = "https://files.pythonhosted.org/packages/ec/fa/dce098f4cdf7621aa8f7b4f919ce545891f489482f0bfa5102f3eca8608b/identify-2.6.5-py2.py3-none-any.whl", hash = "sha256:14181a47091eb75b337af4c23078c9d09225cd4c48929f521f3bf16b09d02566", size = 99078 }, ] [[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 } wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] [[package]] name = "ifaddr" version = "0.2.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e8/ac/fb4c578f4a3256561548cd825646680edcadb9440f3f68add95ade1eb791/ifaddr-0.2.0.tar.gz", hash = "sha256:cc0cbfcaabf765d44595825fb96a99bb12c79716b73b44330ea38ee2b0c4aed4", size = 10485 } wheels = [ { url = "https://files.pythonhosted.org/packages/9c/1f/19ebc343cc71a7ffa78f17018535adc5cbdd87afb31d7c34874680148b32/ifaddr-0.2.0-py3-none-any.whl", hash = "sha256:085e0305cfe6f16ab12d72e2024030f5d52674afad6911bb1eee207177b8a748", size = 12314 }, ] [[package]] name = "iniconfig" version = "2.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } wheels = [ { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, ] [[package]] name = "isort" version = "5.13.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/87/f9/c1eb8635a24e87ade2efce21e3ce8cd6b8630bb685ddc9cdaca1349b2eb5/isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109", size = 175303 } wheels = [ { url = "https://files.pythonhosted.org/packages/d1/b3/8def84f539e7d2289a02f0524b944b15d7c75dab7628bedf1c4f0992029c/isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6", size = 92310 }, ] [[package]] name = "markdown-it-py" version = "3.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mdurl" }, ] sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } wheels = [ { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, ] [[package]] name = "mashumaro" version = "3.15" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f3/c1/7b687c8b993202e2eb49e559b25599d8e85f1b6d92ce676c8801226b8bdf/mashumaro-3.15.tar.gz", hash = "sha256:32a2a38a1e942a07f2cbf9c3061cb2a247714ee53e36a5958548b66bd116d0a9", size = 188646 } wheels = [ { url = "https://files.pythonhosted.org/packages/f9/59/595eabaa779c87a72d65864351e0fdd2359d7d73967d5ed9f2f0c6186fa3/mashumaro-3.15-py3-none-any.whl", hash = "sha256:cdd45ef5a4d09860846a3ee37a4c2f5f4bc70eb158caa55648c4c99451ca6c4c", size = 93761 }, ] [[package]] name = "mccabe" version = "0.7.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658 } wheels = [ { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350 }, ] [[package]] name = "mdurl" version = "0.1.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, ] [[package]] name = "multidict" version = "6.1.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d6/be/504b89a5e9ca731cd47487e91c469064f8ae5af93b7259758dcfc2b9c848/multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a", size = 64002 } wheels = [ { url = "https://files.pythonhosted.org/packages/93/13/df3505a46d0cd08428e4c8169a196131d1b0c4b515c3649829258843dde6/multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6", size = 48570 }, { url = "https://files.pythonhosted.org/packages/f0/e1/a215908bfae1343cdb72f805366592bdd60487b4232d039c437fe8f5013d/multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156", size = 29316 }, { url = "https://files.pythonhosted.org/packages/70/0f/6dc70ddf5d442702ed74f298d69977f904960b82368532c88e854b79f72b/multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb", size = 29640 }, { url = "https://files.pythonhosted.org/packages/d8/6d/9c87b73a13d1cdea30b321ef4b3824449866bd7f7127eceed066ccb9b9ff/multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b", size = 131067 }, { url = "https://files.pythonhosted.org/packages/cc/1e/1b34154fef373371fd6c65125b3d42ff5f56c7ccc6bfff91b9b3c60ae9e0/multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72", size = 138507 }, { url = "https://files.pythonhosted.org/packages/fb/e0/0bc6b2bac6e461822b5f575eae85da6aae76d0e2a79b6665d6206b8e2e48/multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304", size = 133905 }, { url = "https://files.pythonhosted.org/packages/ba/af/73d13b918071ff9b2205fcf773d316e0f8fefb4ec65354bbcf0b10908cc6/multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351", size = 129004 }, { url = "https://files.pythonhosted.org/packages/74/21/23960627b00ed39643302d81bcda44c9444ebcdc04ee5bedd0757513f259/multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb", size = 121308 }, { url = "https://files.pythonhosted.org/packages/8b/5c/cf282263ffce4a596ed0bb2aa1a1dddfe1996d6a62d08842a8d4b33dca13/multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3", size = 132608 }, { url = "https://files.pythonhosted.org/packages/d7/3e/97e778c041c72063f42b290888daff008d3ab1427f5b09b714f5a8eff294/multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399", size = 127029 }, { url = "https://files.pythonhosted.org/packages/47/ac/3efb7bfe2f3aefcf8d103e9a7162572f01936155ab2f7ebcc7c255a23212/multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423", size = 137594 }, { url = "https://files.pythonhosted.org/packages/42/9b/6c6e9e8dc4f915fc90a9b7798c44a30773dea2995fdcb619870e705afe2b/multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3", size = 134556 }, { url = "https://files.pythonhosted.org/packages/1d/10/8e881743b26aaf718379a14ac58572a240e8293a1c9d68e1418fb11c0f90/multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753", size = 130993 }, { url = "https://files.pythonhosted.org/packages/45/84/3eb91b4b557442802d058a7579e864b329968c8d0ea57d907e7023c677f2/multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80", size = 26405 }, { url = "https://files.pythonhosted.org/packages/9f/0b/ad879847ecbf6d27e90a6eabb7eff6b62c129eefe617ea45eae7c1f0aead/multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926", size = 28795 }, { url = "https://files.pythonhosted.org/packages/fd/16/92057c74ba3b96d5e211b553895cd6dc7cc4d1e43d9ab8fafc727681ef71/multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa", size = 48713 }, { url = "https://files.pythonhosted.org/packages/94/3d/37d1b8893ae79716179540b89fc6a0ee56b4a65fcc0d63535c6f5d96f217/multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436", size = 29516 }, { url = "https://files.pythonhosted.org/packages/a2/12/adb6b3200c363062f805275b4c1e656be2b3681aada66c80129932ff0bae/multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761", size = 29557 }, { url = "https://files.pythonhosted.org/packages/47/e9/604bb05e6e5bce1e6a5cf80a474e0f072e80d8ac105f1b994a53e0b28c42/multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e", size = 130170 }, { url = "https://files.pythonhosted.org/packages/7e/13/9efa50801785eccbf7086b3c83b71a4fb501a4d43549c2f2f80b8787d69f/multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef", size = 134836 }, { url = "https://files.pythonhosted.org/packages/bf/0f/93808b765192780d117814a6dfcc2e75de6dcc610009ad408b8814dca3ba/multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95", size = 133475 }, { url = "https://files.pythonhosted.org/packages/d3/c8/529101d7176fe7dfe1d99604e48d69c5dfdcadb4f06561f465c8ef12b4df/multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925", size = 131049 }, { url = "https://files.pythonhosted.org/packages/ca/0c/fc85b439014d5a58063e19c3a158a889deec399d47b5269a0f3b6a2e28bc/multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966", size = 120370 }, { url = "https://files.pythonhosted.org/packages/db/46/d4416eb20176492d2258fbd47b4abe729ff3b6e9c829ea4236f93c865089/multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305", size = 125178 }, { url = "https://files.pythonhosted.org/packages/5b/46/73697ad7ec521df7de5531a32780bbfd908ded0643cbe457f981a701457c/multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2", size = 119567 }, { url = "https://files.pythonhosted.org/packages/cd/ed/51f060e2cb0e7635329fa6ff930aa5cffa17f4c7f5c6c3ddc3500708e2f2/multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2", size = 129822 }, { url = "https://files.pythonhosted.org/packages/df/9e/ee7d1954b1331da3eddea0c4e08d9142da5f14b1321c7301f5014f49d492/multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6", size = 128656 }, { url = "https://files.pythonhosted.org/packages/77/00/8538f11e3356b5d95fa4b024aa566cde7a38aa7a5f08f4912b32a037c5dc/multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3", size = 125360 }, { url = "https://files.pythonhosted.org/packages/be/05/5d334c1f2462d43fec2363cd00b1c44c93a78c3925d952e9a71caf662e96/multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133", size = 26382 }, { url = "https://files.pythonhosted.org/packages/a3/bf/f332a13486b1ed0496d624bcc7e8357bb8053823e8cd4b9a18edc1d97e73/multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1", size = 28529 }, { url = "https://files.pythonhosted.org/packages/22/67/1c7c0f39fe069aa4e5d794f323be24bf4d33d62d2a348acdb7991f8f30db/multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008", size = 48771 }, { url = "https://files.pythonhosted.org/packages/3c/25/c186ee7b212bdf0df2519eacfb1981a017bda34392c67542c274651daf23/multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f", size = 29533 }, { url = "https://files.pythonhosted.org/packages/67/5e/04575fd837e0958e324ca035b339cea174554f6f641d3fb2b4f2e7ff44a2/multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28", size = 29595 }, { url = "https://files.pythonhosted.org/packages/d3/b2/e56388f86663810c07cfe4a3c3d87227f3811eeb2d08450b9e5d19d78876/multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b", size = 130094 }, { url = "https://files.pythonhosted.org/packages/6c/ee/30ae9b4186a644d284543d55d491fbd4239b015d36b23fea43b4c94f7052/multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c", size = 134876 }, { url = "https://files.pythonhosted.org/packages/84/c7/70461c13ba8ce3c779503c70ec9d0345ae84de04521c1f45a04d5f48943d/multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3", size = 133500 }, { url = "https://files.pythonhosted.org/packages/4a/9f/002af221253f10f99959561123fae676148dd730e2daa2cd053846a58507/multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44", size = 131099 }, { url = "https://files.pythonhosted.org/packages/82/42/d1c7a7301d52af79d88548a97e297f9d99c961ad76bbe6f67442bb77f097/multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2", size = 120403 }, { url = "https://files.pythonhosted.org/packages/68/f3/471985c2c7ac707547553e8f37cff5158030d36bdec4414cb825fbaa5327/multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3", size = 125348 }, { url = "https://files.pythonhosted.org/packages/67/2c/e6df05c77e0e433c214ec1d21ddd203d9a4770a1f2866a8ca40a545869a0/multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa", size = 119673 }, { url = "https://files.pythonhosted.org/packages/c5/cd/bc8608fff06239c9fb333f9db7743a1b2eafe98c2666c9a196e867a3a0a4/multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa", size = 129927 }, { url = "https://files.pythonhosted.org/packages/44/8e/281b69b7bc84fc963a44dc6e0bbcc7150e517b91df368a27834299a526ac/multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4", size = 128711 }, { url = "https://files.pythonhosted.org/packages/12/a4/63e7cd38ed29dd9f1881d5119f272c898ca92536cdb53ffe0843197f6c85/multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6", size = 125519 }, { url = "https://files.pythonhosted.org/packages/38/e0/4f5855037a72cd8a7a2f60a3952d9aa45feedb37ae7831642102604e8a37/multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81", size = 26426 }, { url = "https://files.pythonhosted.org/packages/7e/a5/17ee3a4db1e310b7405f5d25834460073a8ccd86198ce044dfaf69eac073/multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774", size = 28531 }, { url = "https://files.pythonhosted.org/packages/99/b7/b9e70fde2c0f0c9af4cc5277782a89b66d35948ea3369ec9f598358c3ac5/multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506", size = 10051 }, ] [[package]] name = "mypy" version = "1.14.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mypy-extensions" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051 } wheels = [ { url = "https://files.pythonhosted.org/packages/da/11/a9422850fd506edbcdc7f6090682ecceaf1f87b9dd847f9df79942da8506/mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c", size = 11120432 }, { url = "https://files.pythonhosted.org/packages/b6/9e/47e450fd39078d9c02d620545b2cb37993a8a8bdf7db3652ace2f80521ca/mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1", size = 10279515 }, { url = "https://files.pythonhosted.org/packages/01/b5/6c8d33bd0f851a7692a8bfe4ee75eb82b6983a3cf39e5e32a5d2a723f0c1/mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8", size = 12025791 }, { url = "https://files.pythonhosted.org/packages/f0/4c/e10e2c46ea37cab5c471d0ddaaa9a434dc1d28650078ac1b56c2d7b9b2e4/mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f", size = 12749203 }, { url = "https://files.pythonhosted.org/packages/88/55/beacb0c69beab2153a0f57671ec07861d27d735a0faff135a494cd4f5020/mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1", size = 12885900 }, { url = "https://files.pythonhosted.org/packages/a2/75/8c93ff7f315c4d086a2dfcde02f713004357d70a163eddb6c56a6a5eff40/mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae", size = 9777869 }, { url = "https://files.pythonhosted.org/packages/43/1b/b38c079609bb4627905b74fc6a49849835acf68547ac33d8ceb707de5f52/mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", size = 11266668 }, { url = "https://files.pythonhosted.org/packages/6b/75/2ed0d2964c1ffc9971c729f7a544e9cd34b2cdabbe2d11afd148d7838aa2/mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", size = 10254060 }, { url = "https://files.pythonhosted.org/packages/a1/5f/7b8051552d4da3c51bbe8fcafffd76a6823779101a2b198d80886cd8f08e/mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", size = 11933167 }, { url = "https://files.pythonhosted.org/packages/04/90/f53971d3ac39d8b68bbaab9a4c6c58c8caa4d5fd3d587d16f5927eeeabe1/mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", size = 12864341 }, { url = "https://files.pythonhosted.org/packages/03/d2/8bc0aeaaf2e88c977db41583559319f1821c069e943ada2701e86d0430b7/mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89", size = 12972991 }, { url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016 }, { url = "https://files.pythonhosted.org/packages/9e/15/bb6a686901f59222275ab228453de741185f9d54fecbaacec041679496c6/mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255", size = 11252097 }, { url = "https://files.pythonhosted.org/packages/f8/b3/8b0f74dfd072c802b7fa368829defdf3ee1566ba74c32a2cb2403f68024c/mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34", size = 10239728 }, { url = "https://files.pythonhosted.org/packages/c5/9b/4fd95ab20c52bb5b8c03cc49169be5905d931de17edfe4d9d2986800b52e/mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a", size = 11924965 }, { url = "https://files.pythonhosted.org/packages/56/9d/4a236b9c57f5d8f08ed346914b3f091a62dd7e19336b2b2a0d85485f82ff/mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", size = 12867660 }, { url = "https://files.pythonhosted.org/packages/40/88/a61a5497e2f68d9027de2bb139c7bb9abaeb1be1584649fa9d807f80a338/mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", size = 12969198 }, { url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276 }, { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 }, ] [[package]] name = "mypy-extensions" version = "1.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 } wheels = [ { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, ] [[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 } wheels = [ { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 }, ] [[package]] name = "orjson" version = "3.10.15" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ae/f9/5dea21763eeff8c1590076918a446ea3d6140743e0e36f58f369928ed0f4/orjson-3.10.15.tar.gz", hash = "sha256:05ca7fe452a2e9d8d9d706a2984c95b9c2ebc5db417ce0b7a49b91d50642a23e", size = 5282482 } wheels = [ { url = "https://files.pythonhosted.org/packages/7a/a2/21b25ce4a2c71dbb90948ee81bd7a42b4fbfc63162e57faf83157d5540ae/orjson-3.10.15-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:c4cc83960ab79a4031f3119cc4b1a1c627a3dc09df125b27c4201dff2af7eaa6", size = 249533 }, { url = "https://files.pythonhosted.org/packages/b2/85/2076fc12d8225698a51278009726750c9c65c846eda741e77e1761cfef33/orjson-3.10.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ddbeef2481d895ab8be5185f2432c334d6dec1f5d1933a9c83014d188e102cef", size = 125230 }, { url = "https://files.pythonhosted.org/packages/06/df/a85a7955f11274191eccf559e8481b2be74a7c6d43075d0a9506aa80284d/orjson-3.10.15-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e590a0477b23ecd5b0ac865b1b907b01b3c5535f5e8a8f6ab0e503efb896334", size = 150148 }, { url = "https://files.pythonhosted.org/packages/37/b3/94c55625a29b8767c0eed194cb000b3787e3c23b4cdd13be17bae6ccbb4b/orjson-3.10.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6be38bd103d2fd9bdfa31c2720b23b5d47c6796bcb1d1b598e3924441b4298d", size = 139749 }, { url = "https://files.pythonhosted.org/packages/53/ba/c608b1e719971e8ddac2379f290404c2e914cf8e976369bae3cad88768b1/orjson-3.10.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff4f6edb1578960ed628a3b998fa54d78d9bb3e2eb2cfc5c2a09732431c678d0", size = 154558 }, { url = "https://files.pythonhosted.org/packages/b2/c4/c1fb835bb23ad788a39aa9ebb8821d51b1c03588d9a9e4ca7de5b354fdd5/orjson-3.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0482b21d0462eddd67e7fce10b89e0b6ac56570424662b685a0d6fccf581e13", size = 130349 }, { url = "https://files.pythonhosted.org/packages/78/14/bb2b48b26ab3c570b284eb2157d98c1ef331a8397f6c8bd983b270467f5c/orjson-3.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bb5cc3527036ae3d98b65e37b7986a918955f85332c1ee07f9d3f82f3a6899b5", size = 138513 }, { url = "https://files.pythonhosted.org/packages/4a/97/d5b353a5fe532e92c46467aa37e637f81af8468aa894cd77d2ec8a12f99e/orjson-3.10.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d569c1c462912acdd119ccbf719cf7102ea2c67dd03b99edcb1a3048651ac96b", size = 130942 }, { url = "https://files.pythonhosted.org/packages/b5/5d/a067bec55293cca48fea8b9928cfa84c623be0cce8141d47690e64a6ca12/orjson-3.10.15-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:1e6d33efab6b71d67f22bf2962895d3dc6f82a6273a965fab762e64fa90dc399", size = 414717 }, { url = "https://files.pythonhosted.org/packages/6f/9a/1485b8b05c6b4c4db172c438cf5db5dcfd10e72a9bc23c151a1137e763e0/orjson-3.10.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c33be3795e299f565681d69852ac8c1bc5c84863c0b0030b2b3468843be90388", size = 141033 }, { url = "https://files.pythonhosted.org/packages/f8/d2/fc67523656e43a0c7eaeae9007c8b02e86076b15d591e9be11554d3d3138/orjson-3.10.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:eea80037b9fae5339b214f59308ef0589fc06dc870578b7cce6d71eb2096764c", size = 129720 }, { url = "https://files.pythonhosted.org/packages/79/42/f58c7bd4e5b54da2ce2ef0331a39ccbbaa7699b7f70206fbf06737c9ed7d/orjson-3.10.15-cp311-cp311-win32.whl", hash = "sha256:d5ac11b659fd798228a7adba3e37c010e0152b78b1982897020a8e019a94882e", size = 142473 }, { url = "https://files.pythonhosted.org/packages/00/f8/bb60a4644287a544ec81df1699d5b965776bc9848d9029d9f9b3402ac8bb/orjson-3.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:cf45e0214c593660339ef63e875f32ddd5aa3b4adc15e662cdb80dc49e194f8e", size = 133570 }, { url = "https://files.pythonhosted.org/packages/66/85/22fe737188905a71afcc4bf7cc4c79cd7f5bbe9ed1fe0aac4ce4c33edc30/orjson-3.10.15-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9d11c0714fc85bfcf36ada1179400862da3288fc785c30e8297844c867d7505a", size = 249504 }, { url = "https://files.pythonhosted.org/packages/48/b7/2622b29f3afebe938a0a9037e184660379797d5fd5234e5998345d7a5b43/orjson-3.10.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dba5a1e85d554e3897fa9fe6fbcff2ed32d55008973ec9a2b992bd9a65d2352d", size = 125080 }, { url = "https://files.pythonhosted.org/packages/ce/8f/0b72a48f4403d0b88b2a41450c535b3e8989e8a2d7800659a967efc7c115/orjson-3.10.15-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7723ad949a0ea502df656948ddd8b392780a5beaa4c3b5f97e525191b102fff0", size = 150121 }, { url = "https://files.pythonhosted.org/packages/06/ec/acb1a20cd49edb2000be5a0404cd43e3c8aad219f376ac8c60b870518c03/orjson-3.10.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6fd9bc64421e9fe9bd88039e7ce8e58d4fead67ca88e3a4014b143cec7684fd4", size = 139796 }, { url = "https://files.pythonhosted.org/packages/33/e1/f7840a2ea852114b23a52a1c0b2bea0a1ea22236efbcdb876402d799c423/orjson-3.10.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dadba0e7b6594216c214ef7894c4bd5f08d7c0135f4dd0145600be4fbcc16767", size = 154636 }, { url = "https://files.pythonhosted.org/packages/fa/da/31543337febd043b8fa80a3b67de627669b88c7b128d9ad4cc2ece005b7a/orjson-3.10.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48f59114fe318f33bbaee8ebeda696d8ccc94c9e90bc27dbe72153094e26f41", size = 130621 }, { url = "https://files.pythonhosted.org/packages/ed/78/66115dc9afbc22496530d2139f2f4455698be444c7c2475cb48f657cefc9/orjson-3.10.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:035fb83585e0f15e076759b6fedaf0abb460d1765b6a36f48018a52858443514", size = 138516 }, { url = "https://files.pythonhosted.org/packages/22/84/cd4f5fb5427ffcf823140957a47503076184cb1ce15bcc1165125c26c46c/orjson-3.10.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d13b7fe322d75bf84464b075eafd8e7dd9eae05649aa2a5354cfa32f43c59f17", size = 130762 }, { url = "https://files.pythonhosted.org/packages/93/1f/67596b711ba9f56dd75d73b60089c5c92057f1130bb3a25a0f53fb9a583b/orjson-3.10.15-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:7066b74f9f259849629e0d04db6609db4cf5b973248f455ba5d3bd58a4daaa5b", size = 414700 }, { url = "https://files.pythonhosted.org/packages/7c/0c/6a3b3271b46443d90efb713c3e4fe83fa8cd71cda0d11a0f69a03f437c6e/orjson-3.10.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:88dc3f65a026bd3175eb157fea994fca6ac7c4c8579fc5a86fc2114ad05705b7", size = 141077 }, { url = "https://files.pythonhosted.org/packages/3b/9b/33c58e0bfc788995eccd0d525ecd6b84b40d7ed182dd0751cd4c1322ac62/orjson-3.10.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b342567e5465bd99faa559507fe45e33fc76b9fb868a63f1642c6bc0735ad02a", size = 129898 }, { url = "https://files.pythonhosted.org/packages/01/c1/d577ecd2e9fa393366a1ea0a9267f6510d86e6c4bb1cdfb9877104cac44c/orjson-3.10.15-cp312-cp312-win32.whl", hash = "sha256:0a4f27ea5617828e6b58922fdbec67b0aa4bb844e2d363b9244c47fa2180e665", size = 142566 }, { url = "https://files.pythonhosted.org/packages/ed/eb/a85317ee1732d1034b92d56f89f1de4d7bf7904f5c8fb9dcdd5b1c83917f/orjson-3.10.15-cp312-cp312-win_amd64.whl", hash = "sha256:ef5b87e7aa9545ddadd2309efe6824bd3dd64ac101c15dae0f2f597911d46eaa", size = 133732 }, { url = "https://files.pythonhosted.org/packages/06/10/fe7d60b8da538e8d3d3721f08c1b7bff0491e8fa4dd3bf11a17e34f4730e/orjson-3.10.15-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:bae0e6ec2b7ba6895198cd981b7cca95d1487d0147c8ed751e5632ad16f031a6", size = 249399 }, { url = "https://files.pythonhosted.org/packages/6b/83/52c356fd3a61abd829ae7e4366a6fe8e8863c825a60d7ac5156067516edf/orjson-3.10.15-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93ce145b2db1252dd86af37d4165b6faa83072b46e3995ecc95d4b2301b725a", size = 125044 }, { url = "https://files.pythonhosted.org/packages/55/b2/d06d5901408e7ded1a74c7c20d70e3a127057a6d21355f50c90c0f337913/orjson-3.10.15-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c203f6f969210128af3acae0ef9ea6aab9782939f45f6fe02d05958fe761ef9", size = 150066 }, { url = "https://files.pythonhosted.org/packages/75/8c/60c3106e08dc593a861755781c7c675a566445cc39558677d505878d879f/orjson-3.10.15-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8918719572d662e18b8af66aef699d8c21072e54b6c82a3f8f6404c1f5ccd5e0", size = 139737 }, { url = "https://files.pythonhosted.org/packages/6a/8c/ae00d7d0ab8a4490b1efeb01ad4ab2f1982e69cc82490bf8093407718ff5/orjson-3.10.15-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f71eae9651465dff70aa80db92586ad5b92df46a9373ee55252109bb6b703307", size = 154804 }, { url = "https://files.pythonhosted.org/packages/22/86/65dc69bd88b6dd254535310e97bc518aa50a39ef9c5a2a5d518e7a223710/orjson-3.10.15-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e117eb299a35f2634e25ed120c37c641398826c2f5a3d3cc39f5993b96171b9e", size = 130583 }, { url = "https://files.pythonhosted.org/packages/bb/00/6fe01ededb05d52be42fabb13d93a36e51f1fd9be173bd95707d11a8a860/orjson-3.10.15-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:13242f12d295e83c2955756a574ddd6741c81e5b99f2bef8ed8d53e47a01e4b7", size = 138465 }, { url = "https://files.pythonhosted.org/packages/db/2f/4cc151c4b471b0cdc8cb29d3eadbce5007eb0475d26fa26ed123dca93b33/orjson-3.10.15-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7946922ada8f3e0b7b958cc3eb22cfcf6c0df83d1fe5521b4a100103e3fa84c8", size = 130742 }, { url = "https://files.pythonhosted.org/packages/9f/13/8a6109e4b477c518498ca37963d9c0eb1508b259725553fb53d53b20e2ea/orjson-3.10.15-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b7155eb1623347f0f22c38c9abdd738b287e39b9982e1da227503387b81b34ca", size = 414669 }, { url = "https://files.pythonhosted.org/packages/22/7b/1d229d6d24644ed4d0a803de1b0e2df832032d5beda7346831c78191b5b2/orjson-3.10.15-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:208beedfa807c922da4e81061dafa9c8489c6328934ca2a562efa707e049e561", size = 141043 }, { url = "https://files.pythonhosted.org/packages/cc/d3/6dc91156cf12ed86bed383bcb942d84d23304a1e57b7ab030bf60ea130d6/orjson-3.10.15-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eca81f83b1b8c07449e1d6ff7074e82e3fd6777e588f1a6632127f286a968825", size = 129826 }, { url = "https://files.pythonhosted.org/packages/b3/38/c47c25b86f6996f1343be721b6ea4367bc1c8bc0fc3f6bbcd995d18cb19d/orjson-3.10.15-cp313-cp313-win32.whl", hash = "sha256:c03cd6eea1bd3b949d0d007c8d57049aa2b39bd49f58b4b2af571a5d3833d890", size = 142542 }, { url = "https://files.pythonhosted.org/packages/27/f1/1d7ec15b20f8ce9300bc850de1e059132b88990e46cd0ccac29cbf11e4f9/orjson-3.10.15-cp313-cp313-win_amd64.whl", hash = "sha256:fd56a26a04f6ba5fb2045b0acc487a63162a958ed837648c5781e1fe3316cfbf", size = 133444 }, ] [[package]] name = "packaging" version = "24.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } wheels = [ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, ] [[package]] name = "pathspec" version = "0.12.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } wheels = [ { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, ] [[package]] name = "peblar" version = "0.0.0" source = { editable = "." } dependencies = [ { name = "aiohttp" }, { name = "awesomeversion" }, { name = "backoff" }, { name = "mashumaro" }, { name = "orjson" }, { name = "yarl" }, ] [package.optional-dependencies] cli = [ { name = "typer" }, { name = "zeroconf" }, ] [package.dev-dependencies] dev = [ { name = "aresponses" }, { name = "codespell" }, { name = "covdefaults" }, { name = "coverage", extra = ["toml"] }, { name = "mypy" }, { name = "pre-commit" }, { name = "pre-commit-hooks" }, { name = "pylint" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, { name = "ruff" }, { name = "syrupy" }, { name = "yamllint" }, ] [package.metadata] requires-dist = [ { name = "aiohttp", specifier = ">=3.0.0" }, { name = "awesomeversion", specifier = ">=22.8.0" }, { name = "backoff", specifier = ">=2.2.1" }, { name = "mashumaro", specifier = ">=3.10" }, { name = "orjson", specifier = ">=3.9.8" }, { name = "typer", marker = "extra == 'cli'", specifier = ">=0.15.1" }, { name = "yarl", specifier = ">=1.6.0" }, { name = "zeroconf", marker = "extra == 'cli'", specifier = ">=0.126.0" }, ] [package.metadata.requires-dev] dev = [ { name = "aresponses", specifier = "==3.0.0" }, { name = "codespell", specifier = "==2.4.0" }, { name = "covdefaults", specifier = "==2.3.0" }, { name = "coverage", extras = ["toml"], specifier = "==7.6.10" }, { name = "mypy", specifier = "==1.14.1" }, { name = "pre-commit", specifier = "==4.1.0" }, { name = "pre-commit-hooks", specifier = "==5.0.0" }, { name = "pylint", specifier = "==3.3.3" }, { name = "pytest", specifier = "==8.3.4" }, { name = "pytest-asyncio", specifier = "==0.25.2" }, { name = "pytest-cov", specifier = "==6.0.0" }, { name = "ruff", specifier = "==0.9.2" }, { name = "syrupy", specifier = "==4.8.1" }, { name = "yamllint", specifier = "==1.35.1" }, ] [[package]] name = "platformdirs" version = "4.3.6" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 } wheels = [ { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 }, ] [[package]] name = "pluggy" version = "1.5.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } wheels = [ { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, ] [[package]] name = "pre-commit" version = "4.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cfgv" }, { name = "identify" }, { name = "nodeenv" }, { name = "pyyaml" }, { name = "virtualenv" }, ] sdist = { url = "https://files.pythonhosted.org/packages/2a/13/b62d075317d8686071eb843f0bb1f195eb332f48869d3c31a4c6f1e063ac/pre_commit-4.1.0.tar.gz", hash = "sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4", size = 193330 } wheels = [ { url = "https://files.pythonhosted.org/packages/43/b3/df14c580d82b9627d173ceea305ba898dca135feb360b6d84019d0803d3b/pre_commit-4.1.0-py2.py3-none-any.whl", hash = "sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b", size = 220560 }, ] [[package]] name = "pre-commit-hooks" version = "5.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ruamel-yaml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ac/7d/3299241a753c738d114600c360d754550b28c285281dc6a5132c4ccfae65/pre_commit_hooks-5.0.0.tar.gz", hash = "sha256:10626959a9eaf602fbfc22bc61b6e75801436f82326bfcee82bb1f2fc4bc646e", size = 29747 } wheels = [ { url = "https://files.pythonhosted.org/packages/1e/29/db1d855a661c02dbde5cab3057969133fcc62e7a0c6393e48fe9d0e81679/pre_commit_hooks-5.0.0-py2.py3-none-any.whl", hash = "sha256:8d71cfb582c5c314a5498d94e0104b6567a8b93fb35903ea845c491f4e290a7a", size = 41245 }, ] [[package]] name = "propcache" version = "0.2.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/20/c8/2a13f78d82211490855b2fb303b6721348d0787fdd9a12ac46d99d3acde1/propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64", size = 41735 } wheels = [ { url = "https://files.pythonhosted.org/packages/bc/0f/2913b6791ebefb2b25b4efd4bb2299c985e09786b9f5b19184a88e5778dd/propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16", size = 79297 }, { url = "https://files.pythonhosted.org/packages/cf/73/af2053aeccd40b05d6e19058419ac77674daecdd32478088b79375b9ab54/propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717", size = 45611 }, { url = "https://files.pythonhosted.org/packages/3c/09/8386115ba7775ea3b9537730e8cf718d83bbf95bffe30757ccf37ec4e5da/propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3", size = 45146 }, { url = "https://files.pythonhosted.org/packages/03/7a/793aa12f0537b2e520bf09f4c6833706b63170a211ad042ca71cbf79d9cb/propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9", size = 232136 }, { url = "https://files.pythonhosted.org/packages/f1/38/b921b3168d72111769f648314100558c2ea1d52eb3d1ba7ea5c4aa6f9848/propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787", size = 239706 }, { url = "https://files.pythonhosted.org/packages/14/29/4636f500c69b5edea7786db3c34eb6166f3384b905665ce312a6e42c720c/propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465", size = 238531 }, { url = "https://files.pythonhosted.org/packages/85/14/01fe53580a8e1734ebb704a3482b7829a0ef4ea68d356141cf0994d9659b/propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af", size = 231063 }, { url = "https://files.pythonhosted.org/packages/33/5c/1d961299f3c3b8438301ccfbff0143b69afcc30c05fa28673cface692305/propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7", size = 220134 }, { url = "https://files.pythonhosted.org/packages/00/d0/ed735e76db279ba67a7d3b45ba4c654e7b02bc2f8050671ec365d8665e21/propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f", size = 220009 }, { url = "https://files.pythonhosted.org/packages/75/90/ee8fab7304ad6533872fee982cfff5a53b63d095d78140827d93de22e2d4/propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54", size = 212199 }, { url = "https://files.pythonhosted.org/packages/eb/ec/977ffaf1664f82e90737275873461695d4c9407d52abc2f3c3e24716da13/propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505", size = 214827 }, { url = "https://files.pythonhosted.org/packages/57/48/031fb87ab6081764054821a71b71942161619549396224cbb242922525e8/propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82", size = 228009 }, { url = "https://files.pythonhosted.org/packages/1a/06/ef1390f2524850838f2390421b23a8b298f6ce3396a7cc6d39dedd4047b0/propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca", size = 231638 }, { url = "https://files.pythonhosted.org/packages/38/2a/101e6386d5a93358395da1d41642b79c1ee0f3b12e31727932b069282b1d/propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e", size = 222788 }, { url = "https://files.pythonhosted.org/packages/db/81/786f687951d0979007e05ad9346cd357e50e3d0b0f1a1d6074df334b1bbb/propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034", size = 40170 }, { url = "https://files.pythonhosted.org/packages/cf/59/7cc7037b295d5772eceb426358bb1b86e6cab4616d971bd74275395d100d/propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3", size = 44404 }, { url = "https://files.pythonhosted.org/packages/4c/28/1d205fe49be8b1b4df4c50024e62480a442b1a7b818e734308bb0d17e7fb/propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a", size = 79588 }, { url = "https://files.pythonhosted.org/packages/21/ee/fc4d893f8d81cd4971affef2a6cb542b36617cd1d8ce56b406112cb80bf7/propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0", size = 45825 }, { url = "https://files.pythonhosted.org/packages/4a/de/bbe712f94d088da1d237c35d735f675e494a816fd6f54e9db2f61ef4d03f/propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d", size = 45357 }, { url = "https://files.pythonhosted.org/packages/7f/14/7ae06a6cf2a2f1cb382586d5a99efe66b0b3d0c6f9ac2f759e6f7af9d7cf/propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4", size = 241869 }, { url = "https://files.pythonhosted.org/packages/cc/59/227a78be960b54a41124e639e2c39e8807ac0c751c735a900e21315f8c2b/propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d", size = 247884 }, { url = "https://files.pythonhosted.org/packages/84/58/f62b4ffaedf88dc1b17f04d57d8536601e4e030feb26617228ef930c3279/propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5", size = 248486 }, { url = "https://files.pythonhosted.org/packages/1c/07/ebe102777a830bca91bbb93e3479cd34c2ca5d0361b83be9dbd93104865e/propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24", size = 243649 }, { url = "https://files.pythonhosted.org/packages/ed/bc/4f7aba7f08f520376c4bb6a20b9a981a581b7f2e385fa0ec9f789bb2d362/propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff", size = 229103 }, { url = "https://files.pythonhosted.org/packages/fe/d5/04ac9cd4e51a57a96f78795e03c5a0ddb8f23ec098b86f92de028d7f2a6b/propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f", size = 226607 }, { url = "https://files.pythonhosted.org/packages/e3/f0/24060d959ea41d7a7cc7fdbf68b31852331aabda914a0c63bdb0e22e96d6/propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec", size = 221153 }, { url = "https://files.pythonhosted.org/packages/77/a7/3ac76045a077b3e4de4859a0753010765e45749bdf53bd02bc4d372da1a0/propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348", size = 222151 }, { url = "https://files.pythonhosted.org/packages/e7/af/5e29da6f80cebab3f5a4dcd2a3240e7f56f2c4abf51cbfcc99be34e17f0b/propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6", size = 233812 }, { url = "https://files.pythonhosted.org/packages/8c/89/ebe3ad52642cc5509eaa453e9f4b94b374d81bae3265c59d5c2d98efa1b4/propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6", size = 238829 }, { url = "https://files.pythonhosted.org/packages/e9/2f/6b32f273fa02e978b7577159eae7471b3cfb88b48563b1c2578b2d7ca0bb/propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518", size = 230704 }, { url = "https://files.pythonhosted.org/packages/5c/2e/f40ae6ff5624a5f77edd7b8359b208b5455ea113f68309e2b00a2e1426b6/propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246", size = 40050 }, { url = "https://files.pythonhosted.org/packages/3b/77/a92c3ef994e47180862b9d7d11e37624fb1c00a16d61faf55115d970628b/propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1", size = 44117 }, { url = "https://files.pythonhosted.org/packages/0f/2a/329e0547cf2def8857157f9477669043e75524cc3e6251cef332b3ff256f/propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc", size = 77002 }, { url = "https://files.pythonhosted.org/packages/12/2d/c4df5415e2382f840dc2ecbca0eeb2293024bc28e57a80392f2012b4708c/propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9", size = 44639 }, { url = "https://files.pythonhosted.org/packages/d0/5a/21aaa4ea2f326edaa4e240959ac8b8386ea31dedfdaa636a3544d9e7a408/propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439", size = 44049 }, { url = "https://files.pythonhosted.org/packages/4e/3e/021b6cd86c0acc90d74784ccbb66808b0bd36067a1bf3e2deb0f3845f618/propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536", size = 224819 }, { url = "https://files.pythonhosted.org/packages/3c/57/c2fdeed1b3b8918b1770a133ba5c43ad3d78e18285b0c06364861ef5cc38/propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629", size = 229625 }, { url = "https://files.pythonhosted.org/packages/9d/81/70d4ff57bf2877b5780b466471bebf5892f851a7e2ca0ae7ffd728220281/propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b", size = 232934 }, { url = "https://files.pythonhosted.org/packages/3c/b9/bb51ea95d73b3fb4100cb95adbd4e1acaf2cbb1fd1083f5468eeb4a099a8/propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052", size = 227361 }, { url = "https://files.pythonhosted.org/packages/f1/20/3c6d696cd6fd70b29445960cc803b1851a1131e7a2e4ee261ee48e002bcd/propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce", size = 213904 }, { url = "https://files.pythonhosted.org/packages/a1/cb/1593bfc5ac6d40c010fa823f128056d6bc25b667f5393781e37d62f12005/propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d", size = 212632 }, { url = "https://files.pythonhosted.org/packages/6d/5c/e95617e222be14a34c709442a0ec179f3207f8a2b900273720501a70ec5e/propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce", size = 207897 }, { url = "https://files.pythonhosted.org/packages/8e/3b/56c5ab3dc00f6375fbcdeefdede5adf9bee94f1fab04adc8db118f0f9e25/propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95", size = 208118 }, { url = "https://files.pythonhosted.org/packages/86/25/d7ef738323fbc6ebcbce33eb2a19c5e07a89a3df2fded206065bd5e868a9/propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf", size = 217851 }, { url = "https://files.pythonhosted.org/packages/b3/77/763e6cef1852cf1ba740590364ec50309b89d1c818e3256d3929eb92fabf/propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f", size = 222630 }, { url = "https://files.pythonhosted.org/packages/4f/e9/0f86be33602089c701696fbed8d8c4c07b6ee9605c5b7536fd27ed540c5b/propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30", size = 216269 }, { url = "https://files.pythonhosted.org/packages/cc/02/5ac83217d522394b6a2e81a2e888167e7ca629ef6569a3f09852d6dcb01a/propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6", size = 39472 }, { url = "https://files.pythonhosted.org/packages/f4/33/d6f5420252a36034bc8a3a01171bc55b4bff5df50d1c63d9caa50693662f/propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1", size = 43363 }, { url = "https://files.pythonhosted.org/packages/41/b6/c5319caea262f4821995dca2107483b94a3345d4607ad797c76cb9c36bcc/propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54", size = 11818 }, ] [[package]] name = "pygments" version = "2.19.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } wheels = [ { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, ] [[package]] name = "pylint" version = "3.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "astroid" }, { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "dill" }, { name = "isort" }, { name = "mccabe" }, { name = "platformdirs" }, { name = "tomlkit" }, ] sdist = { url = "https://files.pythonhosted.org/packages/17/fd/e9a739afac274a39596bbe562e9d966db6f3917fdb2bd7322ffc56da0ba2/pylint-3.3.3.tar.gz", hash = "sha256:07c607523b17e6d16e2ae0d7ef59602e332caa762af64203c24b41c27139f36a", size = 1516550 } wheels = [ { url = "https://files.pythonhosted.org/packages/91/e1/26d55acea92b1ea4d33672e48f09ceeb274e84d7d542a4fb9a32a556db46/pylint-3.3.3-py3-none-any.whl", hash = "sha256:26e271a2bc8bce0fc23833805a9076dd9b4d5194e2a02164942cb3cdc37b4183", size = 521918 }, ] [[package]] name = "pytest" version = "8.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, ] sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } wheels = [ { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, ] [[package]] name = "pytest-asyncio" version = "0.25.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] sdist = { url = "https://files.pythonhosted.org/packages/72/df/adcc0d60f1053d74717d21d58c0048479e9cab51464ce0d2965b086bd0e2/pytest_asyncio-0.25.2.tar.gz", hash = "sha256:3f8ef9a98f45948ea91a0ed3dc4268b5326c0e7bce73892acc654df4262ad45f", size = 53950 } wheels = [ { url = "https://files.pythonhosted.org/packages/61/d8/defa05ae50dcd6019a95527200d3b3980043df5aa445d40cb0ef9f7f98ab/pytest_asyncio-0.25.2-py3-none-any.whl", hash = "sha256:0d0bb693f7b99da304a0634afc0a4b19e49d5e0de2d670f38dc4bfa5727c5075", size = 19400 }, ] [[package]] name = "pytest-cov" version = "6.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "coverage", extra = ["toml"] }, { name = "pytest" }, ] sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } wheels = [ { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 }, ] [[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 } wheels = [ { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850 }, { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 }, { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 }, { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 }, ] [[package]] name = "rich" version = "13.9.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown-it-py" }, { name = "pygments" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } wheels = [ { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, ] [[package]] name = "ruamel-yaml" version = "0.18.10" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ruamel-yaml-clib", marker = "python_full_version < '3.13' and platform_python_implementation == 'CPython'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ea/46/f44d8be06b85bc7c4d8c95d658be2b68f27711f279bf9dd0612a5e4794f5/ruamel.yaml-0.18.10.tar.gz", hash = "sha256:20c86ab29ac2153f80a428e1254a8adf686d3383df04490514ca3b79a362db58", size = 143447 } wheels = [ { url = "https://files.pythonhosted.org/packages/c2/36/dfc1ebc0081e6d39924a2cc53654497f967a084a436bb64402dfce4254d9/ruamel.yaml-0.18.10-py3-none-any.whl", hash = "sha256:30f22513ab2301b3d2b577adc121c6471f28734d3d9728581245f1e76468b4f1", size = 117729 }, ] [[package]] name = "ruamel-yaml-clib" version = "0.2.12" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/20/84/80203abff8ea4993a87d823a5f632e4d92831ef75d404c9fc78d0176d2b5/ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f", size = 225315 } wheels = [ { url = "https://files.pythonhosted.org/packages/fb/8f/683c6ad562f558cbc4f7c029abcd9599148c51c54b5ef0f24f2638da9fbb/ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6", size = 132224 }, { url = "https://files.pythonhosted.org/packages/3c/d2/b79b7d695e2f21da020bd44c782490578f300dd44f0a4c57a92575758a76/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d84318609196d6bd6da0edfa25cedfbabd8dbde5140a0a23af29ad4b8f91fb1e", size = 641480 }, { url = "https://files.pythonhosted.org/packages/68/6e/264c50ce2a31473a9fdbf4fa66ca9b2b17c7455b31ef585462343818bd6c/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb43a269eb827806502c7c8efb7ae7e9e9d0573257a46e8e952f4d4caba4f31e", size = 739068 }, { url = "https://files.pythonhosted.org/packages/86/29/88c2567bc893c84d88b4c48027367c3562ae69121d568e8a3f3a8d363f4d/ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52", size = 703012 }, { url = "https://files.pythonhosted.org/packages/11/46/879763c619b5470820f0cd6ca97d134771e502776bc2b844d2adb6e37753/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642", size = 704352 }, { url = "https://files.pythonhosted.org/packages/02/80/ece7e6034256a4186bbe50dee28cd032d816974941a6abf6a9d65e4228a7/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2", size = 737344 }, { url = "https://files.pythonhosted.org/packages/f0/ca/e4106ac7e80efbabdf4bf91d3d32fc424e41418458251712f5672eada9ce/ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3", size = 714498 }, { url = "https://files.pythonhosted.org/packages/67/58/b1f60a1d591b771298ffa0428237afb092c7f29ae23bad93420b1eb10703/ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4", size = 100205 }, { url = "https://files.pythonhosted.org/packages/b4/4f/b52f634c9548a9291a70dfce26ca7ebce388235c93588a1068028ea23fcc/ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb", size = 118185 }, { url = "https://files.pythonhosted.org/packages/48/41/e7a405afbdc26af961678474a55373e1b323605a4f5e2ddd4a80ea80f628/ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632", size = 133433 }, { url = "https://files.pythonhosted.org/packages/ec/b0/b850385604334c2ce90e3ee1013bd911aedf058a934905863a6ea95e9eb4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:943f32bc9dedb3abff9879edc134901df92cfce2c3d5c9348f172f62eb2d771d", size = 647362 }, { url = "https://files.pythonhosted.org/packages/44/d0/3f68a86e006448fb6c005aee66565b9eb89014a70c491d70c08de597f8e4/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c3829bb364fdb8e0332c9931ecf57d9be3519241323c5274bd82f709cebc0c", size = 754118 }, { url = "https://files.pythonhosted.org/packages/52/a9/d39f3c5ada0a3bb2870d7db41901125dbe2434fa4f12ca8c5b83a42d7c53/ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd", size = 706497 }, { url = "https://files.pythonhosted.org/packages/b0/fa/097e38135dadd9ac25aecf2a54be17ddf6e4c23e43d538492a90ab3d71c6/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31", size = 698042 }, { url = "https://files.pythonhosted.org/packages/ec/d5/a659ca6f503b9379b930f13bc6b130c9f176469b73b9834296822a83a132/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680", size = 745831 }, { url = "https://files.pythonhosted.org/packages/db/5d/36619b61ffa2429eeaefaab4f3374666adf36ad8ac6330d855848d7d36fd/ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d", size = 715692 }, { url = "https://files.pythonhosted.org/packages/b1/82/85cb92f15a4231c89b95dfe08b09eb6adca929ef7df7e17ab59902b6f589/ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5", size = 98777 }, { url = "https://files.pythonhosted.org/packages/d7/8f/c3654f6f1ddb75daf3922c3d8fc6005b1ab56671ad56ffb874d908bfa668/ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4", size = 115523 }, { url = "https://files.pythonhosted.org/packages/29/00/4864119668d71a5fa45678f380b5923ff410701565821925c69780356ffa/ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a", size = 132011 }, { url = "https://files.pythonhosted.org/packages/7f/5e/212f473a93ae78c669ffa0cb051e3fee1139cb2d385d2ae1653d64281507/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux2014_aarch64.whl", hash = "sha256:e7e3736715fbf53e9be2a79eb4db68e4ed857017344d697e8b9749444ae57475", size = 642488 }, { url = "https://files.pythonhosted.org/packages/1f/8f/ecfbe2123ade605c49ef769788f79c38ddb1c8fa81e01f4dbf5cf1a44b16/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7e75b4965e1d4690e93021adfcecccbca7d61c7bddd8e22406ef2ff20d74ef", size = 745066 }, { url = "https://files.pythonhosted.org/packages/e2/a9/28f60726d29dfc01b8decdb385de4ced2ced9faeb37a847bd5cf26836815/ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6", size = 701785 }, { url = "https://files.pythonhosted.org/packages/84/7e/8e7ec45920daa7f76046578e4f677a3215fe8f18ee30a9cb7627a19d9b4c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf", size = 693017 }, { url = "https://files.pythonhosted.org/packages/c5/b3/d650eaade4ca225f02a648321e1ab835b9d361c60d51150bac49063b83fa/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1", size = 741270 }, { url = "https://files.pythonhosted.org/packages/87/b8/01c29b924dcbbed75cc45b30c30d565d763b9c4d540545a0eeecffb8f09c/ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01", size = 709059 }, { url = "https://files.pythonhosted.org/packages/30/8c/ed73f047a73638257aa9377ad356bea4d96125b305c34a28766f4445cc0f/ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6", size = 98583 }, { url = "https://files.pythonhosted.org/packages/b0/85/e8e751d8791564dd333d5d9a4eab0a7a115f7e349595417fd50ecae3395c/ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3", size = 115190 }, ] [[package]] name = "ruff" version = "0.9.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/80/63/77ecca9d21177600f551d1c58ab0e5a0b260940ea7312195bd2a4798f8a8/ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0", size = 3553799 } wheels = [ { url = "https://files.pythonhosted.org/packages/af/b9/0e168e4e7fb3af851f739e8f07889b91d1a33a30fca8c29fa3149d6b03ec/ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347", size = 11652408 }, { url = "https://files.pythonhosted.org/packages/2c/22/08ede5db17cf701372a461d1cb8fdde037da1d4fa622b69ac21960e6237e/ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00", size = 11587553 }, { url = "https://files.pythonhosted.org/packages/42/05/dedfc70f0bf010230229e33dec6e7b2235b2a1b8cbb2a991c710743e343f/ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4", size = 11020755 }, { url = "https://files.pythonhosted.org/packages/df/9b/65d87ad9b2e3def67342830bd1af98803af731243da1255537ddb8f22209/ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d", size = 11826502 }, { url = "https://files.pythonhosted.org/packages/93/02/f2239f56786479e1a89c3da9bc9391120057fc6f4a8266a5b091314e72ce/ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c", size = 11390562 }, { url = "https://files.pythonhosted.org/packages/c9/37/d3a854dba9931f8cb1b2a19509bfe59e00875f48ade632e95aefcb7a0aee/ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f", size = 12548968 }, { url = "https://files.pythonhosted.org/packages/fa/c3/c7b812bb256c7a1d5553433e95980934ffa85396d332401f6b391d3c4569/ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684", size = 13187155 }, { url = "https://files.pythonhosted.org/packages/bd/5a/3c7f9696a7875522b66aa9bba9e326e4e5894b4366bd1dc32aa6791cb1ff/ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d", size = 12704674 }, { url = "https://files.pythonhosted.org/packages/be/d6/d908762257a96ce5912187ae9ae86792e677ca4f3dc973b71e7508ff6282/ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df", size = 14529328 }, { url = "https://files.pythonhosted.org/packages/2d/c2/049f1e6755d12d9cd8823242fa105968f34ee4c669d04cac8cea51a50407/ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247", size = 12385955 }, { url = "https://files.pythonhosted.org/packages/91/5a/a9bdb50e39810bd9627074e42743b00e6dc4009d42ae9f9351bc3dbc28e7/ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e", size = 11810149 }, { url = "https://files.pythonhosted.org/packages/e5/fd/57df1a0543182f79a1236e82a79c68ce210efb00e97c30657d5bdb12b478/ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe", size = 11479141 }, { url = "https://files.pythonhosted.org/packages/dc/16/bc3fd1d38974f6775fc152a0554f8c210ff80f2764b43777163c3c45d61b/ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb", size = 12014073 }, { url = "https://files.pythonhosted.org/packages/47/6b/e4ca048a8f2047eb652e1e8c755f384d1b7944f69ed69066a37acd4118b0/ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a", size = 12435758 }, { url = "https://files.pythonhosted.org/packages/c2/40/4d3d6c979c67ba24cf183d29f706051a53c36d78358036a9cd21421582ab/ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145", size = 9796916 }, { url = "https://files.pythonhosted.org/packages/c3/ef/7f548752bdb6867e6939489c87fe4da489ab36191525fadc5cede2a6e8e2/ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5", size = 10773080 }, { url = "https://files.pythonhosted.org/packages/0e/4e/33df635528292bd2d18404e4daabcd74ca8a9853b2e1df85ed3d32d24362/ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6", size = 10001738 }, ] [[package]] name = "shellingham" version = "1.5.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 } wheels = [ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 }, ] [[package]] name = "syrupy" version = "4.8.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c4/32/8b56491ed50ae103c2db14885c29fe765170bdf044fe5868548113da35ef/syrupy-4.8.1.tar.gz", hash = "sha256:8da8c0311e6d92de0b15767768c6ab98982b7b4a4c67083c08fbac3fbad4d44c", size = 50192 } wheels = [ { url = "https://files.pythonhosted.org/packages/80/47/5e8f44ec0f287b08e8c1f3fc63fe1fbe182f07bf606eec903d7827b95e51/syrupy-4.8.1-py3-none-any.whl", hash = "sha256:274f97cbaf44175f5e478a2f3a53559d31f41c66c6bf28131695f94ac893ea00", size = 50326 }, ] [[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 } 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 }, { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { 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 }, { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, ] [[package]] name = "tomlkit" version = "0.13.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/b1/09/a439bec5888f00a54b8b9f05fa94d7f901d6735ef4e55dcec9bc37b5d8fa/tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79", size = 192885 } wheels = [ { url = "https://files.pythonhosted.org/packages/f9/b6/a447b5e4ec71e13871be01ba81f5dfc9d0af7e473da256ff46bc0e24026f/tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde", size = 37955 }, ] [[package]] name = "typer" version = "0.15.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "rich" }, { name = "shellingham" }, { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cb/ce/dca7b219718afd37a0068f4f2530a727c2b74a8b6e8e0c0080a4c0de4fcd/typer-0.15.1.tar.gz", hash = "sha256:a0588c0a7fa68a1978a069818657778f86abe6ff5ea6abf472f940a08bfe4f0a", size = 99789 } wheels = [ { url = "https://files.pythonhosted.org/packages/d0/cc/0a838ba5ca64dc832aa43f727bd586309846b0ffb2ce52422543e6075e8a/typer-0.15.1-py3-none-any.whl", hash = "sha256:7994fb7b8155b64d3402518560648446072864beefd44aa2dc36972a5972e847", size = 44908 }, ] [[package]] name = "typing-extensions" version = "4.12.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } wheels = [ { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, ] [[package]] name = "virtualenv" version = "20.29.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, { name = "filelock" }, { name = "platformdirs" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a7/ca/f23dcb02e161a9bba141b1c08aa50e8da6ea25e6d780528f1d385a3efe25/virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35", size = 7658028 } wheels = [ { url = "https://files.pythonhosted.org/packages/89/9b/599bcfc7064fbe5740919e78c5df18e5dceb0887e676256a1061bb5ae232/virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779", size = 4282379 }, ] [[package]] name = "yamllint" version = "1.35.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pathspec" }, { name = "pyyaml" }, ] sdist = { url = "https://files.pythonhosted.org/packages/da/06/d8cee5c3dfd550cc0a466ead8b321138198485d1034130ac1393cc49d63e/yamllint-1.35.1.tar.gz", hash = "sha256:7a003809f88324fd2c877734f2d575ee7881dd9043360657cc8049c809eba6cd", size = 134583 } wheels = [ { url = "https://files.pythonhosted.org/packages/09/28/2abf1ec14df2d584b9e7ce3b0be458838741e6aaff7a540374ba9af83916/yamllint-1.35.1-py3-none-any.whl", hash = "sha256:2e16e504bb129ff515b37823b472750b36b6de07963bd74b307341ef5ad8bdc3", size = 66738 }, ] [[package]] name = "yarl" version = "1.18.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "idna" }, { name = "multidict" }, { name = "propcache" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b7/9d/4b94a8e6d2b51b599516a5cb88e5bc99b4d8d4583e468057eaa29d5f0918/yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1", size = 181062 } wheels = [ { url = "https://files.pythonhosted.org/packages/40/93/282b5f4898d8e8efaf0790ba6d10e2245d2c9f30e199d1a85cae9356098c/yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069", size = 141555 }, { url = "https://files.pythonhosted.org/packages/6d/9c/0a49af78df099c283ca3444560f10718fadb8a18dc8b3edf8c7bd9fd7d89/yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193", size = 94351 }, { url = "https://files.pythonhosted.org/packages/5a/a1/205ab51e148fdcedad189ca8dd587794c6f119882437d04c33c01a75dece/yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889", size = 92286 }, { url = "https://files.pythonhosted.org/packages/ed/fe/88b690b30f3f59275fb674f5f93ddd4a3ae796c2b62e5bb9ece8a4914b83/yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8", size = 340649 }, { url = "https://files.pythonhosted.org/packages/07/eb/3b65499b568e01f36e847cebdc8d7ccb51fff716dbda1ae83c3cbb8ca1c9/yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca", size = 356623 }, { url = "https://files.pythonhosted.org/packages/33/46/f559dc184280b745fc76ec6b1954de2c55595f0ec0a7614238b9ebf69618/yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8", size = 354007 }, { url = "https://files.pythonhosted.org/packages/af/ba/1865d85212351ad160f19fb99808acf23aab9a0f8ff31c8c9f1b4d671fc9/yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae", size = 344145 }, { url = "https://files.pythonhosted.org/packages/94/cb/5c3e975d77755d7b3d5193e92056b19d83752ea2da7ab394e22260a7b824/yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3", size = 336133 }, { url = "https://files.pythonhosted.org/packages/19/89/b77d3fd249ab52a5c40859815765d35c91425b6bb82e7427ab2f78f5ff55/yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb", size = 347967 }, { url = "https://files.pythonhosted.org/packages/35/bd/f6b7630ba2cc06c319c3235634c582a6ab014d52311e7d7c22f9518189b5/yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e", size = 346397 }, { url = "https://files.pythonhosted.org/packages/18/1a/0b4e367d5a72d1f095318344848e93ea70da728118221f84f1bf6c1e39e7/yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59", size = 350206 }, { url = "https://files.pythonhosted.org/packages/b5/cf/320fff4367341fb77809a2d8d7fe75b5d323a8e1b35710aafe41fdbf327b/yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d", size = 362089 }, { url = "https://files.pythonhosted.org/packages/57/cf/aadba261d8b920253204085268bad5e8cdd86b50162fcb1b10c10834885a/yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e", size = 366267 }, { url = "https://files.pythonhosted.org/packages/54/58/fb4cadd81acdee6dafe14abeb258f876e4dd410518099ae9a35c88d8097c/yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a", size = 359141 }, { url = "https://files.pythonhosted.org/packages/9a/7a/4c571597589da4cd5c14ed2a0b17ac56ec9ee7ee615013f74653169e702d/yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1", size = 84402 }, { url = "https://files.pythonhosted.org/packages/ae/7b/8600250b3d89b625f1121d897062f629883c2f45339623b69b1747ec65fa/yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5", size = 91030 }, { url = "https://files.pythonhosted.org/packages/33/85/bd2e2729752ff4c77338e0102914897512e92496375e079ce0150a6dc306/yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50", size = 142644 }, { url = "https://files.pythonhosted.org/packages/ff/74/1178322cc0f10288d7eefa6e4a85d8d2e28187ccab13d5b844e8b5d7c88d/yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576", size = 94962 }, { url = "https://files.pythonhosted.org/packages/be/75/79c6acc0261e2c2ae8a1c41cf12265e91628c8c58ae91f5ff59e29c0787f/yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640", size = 92795 }, { url = "https://files.pythonhosted.org/packages/6b/32/927b2d67a412c31199e83fefdce6e645247b4fb164aa1ecb35a0f9eb2058/yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2", size = 332368 }, { url = "https://files.pythonhosted.org/packages/19/e5/859fca07169d6eceeaa4fde1997c91d8abde4e9a7c018e371640c2da2b71/yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75", size = 342314 }, { url = "https://files.pythonhosted.org/packages/08/75/76b63ccd91c9e03ab213ef27ae6add2e3400e77e5cdddf8ed2dbc36e3f21/yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512", size = 341987 }, { url = "https://files.pythonhosted.org/packages/1a/e1/a097d5755d3ea8479a42856f51d97eeff7a3a7160593332d98f2709b3580/yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba", size = 336914 }, { url = "https://files.pythonhosted.org/packages/0b/42/e1b4d0e396b7987feceebe565286c27bc085bf07d61a59508cdaf2d45e63/yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb", size = 325765 }, { url = "https://files.pythonhosted.org/packages/7e/18/03a5834ccc9177f97ca1bbb245b93c13e58e8225276f01eedc4cc98ab820/yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272", size = 344444 }, { url = "https://files.pythonhosted.org/packages/c8/03/a713633bdde0640b0472aa197b5b86e90fbc4c5bc05b727b714cd8a40e6d/yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6", size = 340760 }, { url = "https://files.pythonhosted.org/packages/eb/99/f6567e3f3bbad8fd101886ea0276c68ecb86a2b58be0f64077396cd4b95e/yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e", size = 346484 }, { url = "https://files.pythonhosted.org/packages/8e/a9/84717c896b2fc6cb15bd4eecd64e34a2f0a9fd6669e69170c73a8b46795a/yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb", size = 359864 }, { url = "https://files.pythonhosted.org/packages/1e/2e/d0f5f1bef7ee93ed17e739ec8dbcb47794af891f7d165fa6014517b48169/yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393", size = 364537 }, { url = "https://files.pythonhosted.org/packages/97/8a/568d07c5d4964da5b02621a517532adb8ec5ba181ad1687191fffeda0ab6/yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285", size = 357861 }, { url = "https://files.pythonhosted.org/packages/7d/e3/924c3f64b6b3077889df9a1ece1ed8947e7b61b0a933f2ec93041990a677/yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2", size = 84097 }, { url = "https://files.pythonhosted.org/packages/34/45/0e055320daaabfc169b21ff6174567b2c910c45617b0d79c68d7ab349b02/yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477", size = 90399 }, { url = "https://files.pythonhosted.org/packages/30/c7/c790513d5328a8390be8f47be5d52e141f78b66c6c48f48d241ca6bd5265/yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb", size = 140789 }, { url = "https://files.pythonhosted.org/packages/30/aa/a2f84e93554a578463e2edaaf2300faa61c8701f0898725842c704ba5444/yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa", size = 94144 }, { url = "https://files.pythonhosted.org/packages/c6/fc/d68d8f83714b221a85ce7866832cba36d7c04a68fa6a960b908c2c84f325/yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782", size = 91974 }, { url = "https://files.pythonhosted.org/packages/56/4e/d2563d8323a7e9a414b5b25341b3942af5902a2263d36d20fb17c40411e2/yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0", size = 333587 }, { url = "https://files.pythonhosted.org/packages/25/c9/cfec0bc0cac8d054be223e9f2c7909d3e8442a856af9dbce7e3442a8ec8d/yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482", size = 344386 }, { url = "https://files.pythonhosted.org/packages/ab/5d/4c532190113b25f1364d25f4c319322e86232d69175b91f27e3ebc2caf9a/yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186", size = 345421 }, { url = "https://files.pythonhosted.org/packages/23/d1/6cdd1632da013aa6ba18cee4d750d953104a5e7aac44e249d9410a972bf5/yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58", size = 339384 }, { url = "https://files.pythonhosted.org/packages/9a/c4/6b3c39bec352e441bd30f432cda6ba51681ab19bb8abe023f0d19777aad1/yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53", size = 326689 }, { url = "https://files.pythonhosted.org/packages/23/30/07fb088f2eefdc0aa4fc1af4e3ca4eb1a3aadd1ce7d866d74c0f124e6a85/yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2", size = 345453 }, { url = "https://files.pythonhosted.org/packages/63/09/d54befb48f9cd8eec43797f624ec37783a0266855f4930a91e3d5c7717f8/yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8", size = 341872 }, { url = "https://files.pythonhosted.org/packages/91/26/fd0ef9bf29dd906a84b59f0cd1281e65b0c3e08c6aa94b57f7d11f593518/yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1", size = 347497 }, { url = "https://files.pythonhosted.org/packages/d9/b5/14ac7a256d0511b2ac168d50d4b7d744aea1c1aa20c79f620d1059aab8b2/yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a", size = 359981 }, { url = "https://files.pythonhosted.org/packages/ca/b3/d493221ad5cbd18bc07e642894030437e405e1413c4236dd5db6e46bcec9/yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10", size = 366229 }, { url = "https://files.pythonhosted.org/packages/04/56/6a3e2a5d9152c56c346df9b8fb8edd2c8888b1e03f96324d457e5cf06d34/yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8", size = 360383 }, { url = "https://files.pythonhosted.org/packages/fd/b7/4b3c7c7913a278d445cc6284e59b2e62fa25e72758f888b7a7a39eb8423f/yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d", size = 310152 }, { url = "https://files.pythonhosted.org/packages/f5/d5/688db678e987c3e0fb17867970700b92603cadf36c56e5fb08f23e822a0c/yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c", size = 315723 }, { url = "https://files.pythonhosted.org/packages/f5/4b/a06e0ec3d155924f77835ed2d167ebd3b211a7b0853da1cf8d8414d784ef/yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b", size = 45109 }, ] [[package]] name = "zeroconf" version = "0.140.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "ifaddr" }, ] sdist = { url = "https://files.pythonhosted.org/packages/d2/20/e8c3df9312cbd16175b51d180d3fc160411c259e8326f1629135323e8d80/zeroconf-0.140.1.tar.gz", hash = "sha256:477d396cb712247aa5859e59249aabdad3fab1139097794e70b2e4b1625047bf", size = 240320 } wheels = [ { url = "https://files.pythonhosted.org/packages/43/3b/c67f96b90c80e2a9f228dd2ca8800e4b28bda461030e135e5a037a681437/zeroconf-0.140.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d2f2d46585c29ab409297e9f00e691d8c21a6803f9598d7c1b92c4b173807e7b", size = 1919275 }, { url = "https://files.pythonhosted.org/packages/34/aa/a71dd484a03d76aedab9ff1e8d699f4cb7c8e78c17f6036d44e9e1d392f7/zeroconf-0.140.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93c4581b5cf2fdef2019bce47e492ec884b9518a0c0b5b45ffc9679a8594a9e4", size = 1771819 }, { url = "https://files.pythonhosted.org/packages/d7/d7/c276bd3d7fa20913fba75e0a4382137edcafd5dff1ded60daee547232cdf/zeroconf-0.140.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c872b6b2349e010310f239620ffeed11102777ba99044042dc93d19a826cb396", size = 11378244 }, { url = "https://files.pythonhosted.org/packages/fc/7b/bb8837fec5f5a884f9411d29db62fc76145880b260aa6c09a0332df7a5c7/zeroconf-0.140.1-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:6d8c7ae3b0d27690edc4e2d4b9972fd4014a44f58e045aca0c51ad3cd00b4f60", size = 10899391 }, { url = "https://files.pythonhosted.org/packages/2a/e0/55ccb5af81decb9d4a290df2fd61c7c6137409cd696ffe3e32e30648dfc3/zeroconf-0.140.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b481accb4429575b0e7978a81bfd7cb06497be5f1ec89e15357b61b3713da87b", size = 11436195 }, { url = "https://files.pythonhosted.org/packages/f4/78/c92b6cf7dfd940e6589f79b206115113e8fed204813801d9d49af9535249/zeroconf-0.140.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d789fab70ae369394f5df6be29740c47e4aa558ebacd185ad1ea13fe936b02c", size = 11372436 }, { url = "https://files.pythonhosted.org/packages/23/03/db56b42d6aa06f2635948aeb63b610b25b8a76d122258a6247e70c50db24/zeroconf-0.140.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9736f1cac8acc6e595904b5b568e8a40cfc8d845bd66477643c3885cb8a889f6", size = 11266669 }, { url = "https://files.pythonhosted.org/packages/e3/e0/88c2c0b86df91e6dffc66e20a8803f5b078ebe3e3dba68e58f936df5f5f6/zeroconf-0.140.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5c4e57ae92665c276bb688e4b6857196ba128964ce32355065abea10c2243e3a", size = 11765313 }, { url = "https://files.pythonhosted.org/packages/d0/e5/b88522134b8786e7c4e811b3e3c807bef97d5fe9571c6436731d86f79404/zeroconf-0.140.1-cp311-cp311-win32.whl", hash = "sha256:19f311cbf70b94aa2f95f66d42c1d08980d84acd2c17c8c90655b645d238bca0", size = 1424258 }, { url = "https://files.pythonhosted.org/packages/86/1a/345925005730f01c94f6368bf1d2e73460e7a09cc555da11d9d008b8c722/zeroconf-0.140.1-cp311-cp311-win_amd64.whl", hash = "sha256:71dc9ccc0f0e78909813521e4eb7e7d23a145db372f7c76e8e2a7ce2b85a9ff6", size = 1657085 }, { url = "https://files.pythonhosted.org/packages/52/ab/52a1690a3b7ef4f8f513814c40eb6c8adb1255a0d60ce9ef4852e3cd2a14/zeroconf-0.140.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:378fc6a7bb8800a63cc7da858813de1485253a4efdfae38ab1de4e314ae1ee0d", size = 1943170 }, { url = "https://files.pythonhosted.org/packages/d7/dd/d0363084104102d638b1e5683e458a4f6f4ef7c64e19da331d0c295527fd/zeroconf-0.140.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:78a4e5a41401bfa84fba560e103ed97c74c99dee8109c9cc62d0d229d224880d", size = 1791431 }, { url = "https://files.pythonhosted.org/packages/57/d8/284418bacb88358049f0d4028158269d54853129551b0ded3eae9b242e12/zeroconf-0.140.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a0576b66e2281d05271745e1cfb67d3b97ca642c6e0b90d11562bcbcd0dc6fd", size = 11060935 }, { url = "https://files.pythonhosted.org/packages/6f/f9/fd29d5f70109ed74e17d013f6790d0cabe12f0a15c2168053f306820e8e7/zeroconf-0.140.1-cp312-cp312-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:ec131f43010af32d49689456b04c5c04d254e0a5f5612a8289a5a5231c6ed071", size = 10590939 }, { url = "https://files.pythonhosted.org/packages/f1/b1/e1e1e8eac07056a091fffb940dc50c6d91ed6a6b7bee864490cf37c3953d/zeroconf-0.140.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46da31d1545ec7d669f04c26bf368b22110e77adf673d7ae41219779a80cd664", size = 11219365 }, { url = "https://files.pythonhosted.org/packages/63/6d/4c37d354c3e36b1dd326181ce5d883168af581c1df703591c85bc809d34a/zeroconf-0.140.1-cp312-cp312-manylinux_2_36_x86_64.whl", hash = "sha256:58ea89cfa5009ccd0af9e9424a135430e3dff9f3af6dacd96887cc5cd0306daa", size = 11246923 }, { url = "https://files.pythonhosted.org/packages/2c/ef/489f059d1189e1fed1cceb0a5a7bdb654f71db535f526565026bac3cfdb5/zeroconf-0.140.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:14c91a51084f562936fdbfe7484f3512034e31d2aca2d4cb7dacd169d655b5a7", size = 11123382 }, { url = "https://files.pythonhosted.org/packages/b6/c8/527a9f238db812558da038e7cfacc87968677f72fd3a8469143465c7bc7a/zeroconf-0.140.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f93a5c26ee2958568d6ec79a46686b4e8b1998e67d1358156f6b6e8102f51633", size = 11054435 }, { url = "https://files.pythonhosted.org/packages/e7/43/63d04b181fd740e20e4167ae2861671d6986407f14c2de226cc2ec9e3d28/zeroconf-0.140.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:942011249012f674f17fb17c7a961eb32f28cc920c9d11b6317c61510214c59a", size = 11551577 }, { url = "https://files.pythonhosted.org/packages/36/b3/615d5e145711c76d133cba1c34337cf785f325c3e738fc33d8fe7fe85eef/zeroconf-0.140.1-cp312-cp312-win32.whl", hash = "sha256:08ef39d2a6b3337c45b287ba1a303a1147842b6dac23840115eee075c6dd3367", size = 1427940 }, { url = "https://files.pythonhosted.org/packages/cb/1c/e8108574194d530960d51280ef025f525edf7582e805518190a9fae3ef54/zeroconf-0.140.1-cp312-cp312-win_amd64.whl", hash = "sha256:6b193d377898981ae3b8cb1fae0ea5fc6606c9d84930e0affb773f54480f982f", size = 1654261 }, { url = "https://files.pythonhosted.org/packages/42/16/f94e36e61808dda213db4ab9576b65b5fa34708f93aa451991d1a94324db/zeroconf-0.140.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:78b5a29d63d2513230189b4501022912d911e1e12a4633bd1a74eedd08a18045", size = 1920332 }, { url = "https://files.pythonhosted.org/packages/cf/da/f587099e03ed30776fe8d0296a37fb88def16f8c69981ffadac453a38476/zeroconf-0.140.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:969b8c423d6aa9e7921f540b1315b3aef67228759ec6372e0ccff98607c104ae", size = 1771790 }, { url = "https://files.pythonhosted.org/packages/41/1a/2e71bbf8f73342b707a75327fafd2fa393ade8ee43362366ba63f1d2845a/zeroconf-0.140.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9009c88e637f6498e0cc043651cf3370a72e28d3af4ea611137e4d9916047807", size = 10969901 }, { url = "https://files.pythonhosted.org/packages/25/30/17c3ac8cdb902aae102c022a7cb39a7db1537865e02b55f8511d4a7ea29d/zeroconf-0.140.1-cp313-cp313-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:2d5a152cf26fad858e1220e8257be85182a89fcd7a30301d86b9d6418a42fbf4", size = 10490953 }, { url = "https://files.pythonhosted.org/packages/67/0c/f176701862dd49d64c7f9a0a35a468b7377f095f77a01391ccbd8e25c8d4/zeroconf-0.140.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5f91700c6a08feb01703ffad209ecc57b63402f09a564721d89af8e82355aa4", size = 11162943 }, { url = "https://files.pythonhosted.org/packages/32/60/b100e2fa918a44e00ec005fcd822b67a85f2f9737ecbf56cb0944cda0ce9/zeroconf-0.140.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3b3532603a2b7ea7eeca86aeb8064f2158e37a3dc60c441d69f151cba03c7ead", size = 11024922 }, { url = "https://files.pythonhosted.org/packages/dd/ee/b57bdec939affbfeb03a10e8c0ca5aa6b83a34e7aaeeeb25ddeca86cc732/zeroconf-0.140.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:55790ec7f10ad36e56420e3448d0c085e6cc72b4f42908a902ff0f6be9ad7607", size = 10951283 }, { url = "https://files.pythonhosted.org/packages/d3/fb/92a0f07085976ec0d39696a18c4a7b97746d3fb538866bb235c3e9284027/zeroconf-0.140.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b65ce897965f1f1ba9e3f7374556a973d38c404820932080f765ad47932c5420", size = 11466842 }, { url = "https://files.pythonhosted.org/packages/58/13/07b9ab47beafeff7d2e972c509f7ae794ea3f98a1a3f438d12fef022e5d3/zeroconf-0.140.1-cp313-cp313-win32.whl", hash = "sha256:ec55a5f5c3e3457fdbe7021624f499dd8058af652658d6f8f2820278d8af00fd", size = 1423927 }, { url = "https://files.pythonhosted.org/packages/13/f7/af1915f1d2601189104b2bd572b72463f600549e21808ffadbb71ca551ef/zeroconf-0.140.1-cp313-cp313-win_amd64.whl", hash = "sha256:f46fd563ec8e9702a78f34d0ee9a905c4390815a8df16d097b36de40a5d012e7", size = 1649610 }, ]