diff --git a/.gitattributes b/.gitattributes index 4512b2cc9..d6e0c6a82 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,6 +2,11 @@ CHANGELOG.md merge=union *.xlsx binary +*.min.js binary +*.min.css binary +doorstop/core/files/templates/html/output/*.js binary +doorstop/core/files/templates/html/tex-mml-chtml.js binary +doorstop/core/tests/files/published*.html binary # Python, Git, and Cygwin have different ideas about the correct line endings *.yml -text diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 000000000..7deb72d31 --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,13 @@ +changelog: + categories: + - title: Features + labels: + - '*' + exclude: + labels: + - dependencies + - title: Dependencies + labels: + - dependencies + + diff --git a/.github/workflows/change-coverage.yml b/.github/workflows/change-coverage.yml index 7e32465ed..02db7da3a 100644 --- a/.github/workflows/change-coverage.yml +++ b/.github/workflows/change-coverage.yml @@ -24,10 +24,10 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" architecture: x64 - - uses: Gr1N/setup-poetry@v8 + - uses: Gr1N/setup-poetry@v9 - name: Check system dependencies run: make doctor @@ -43,6 +43,6 @@ jobs: - name: Check coverage run: | TEST_INTEGRATION=true poetry run pytest doorstop --doctest-modules --cov=doorstop --cov-report=xml --cov-report=term-missing - git fetch origin develop:develop + git fetch origin main:main # TEST_INTEGRATION=true poetry run diff-cover ./coverage.xml --fail-under=100 --compare-branch=develop - TEST_INTEGRATION=true poetry run diff-cover ./coverage.xml --fail-under=100 --compare-branch=$(git for-each-ref --sort=-committerdate refs/heads/develop | cut -f 1 -d ' ') + TEST_INTEGRATION=true poetry run diff-cover ./coverage.xml --fail-under=100 --compare-branch=$(git for-each-ref --sort=-committerdate refs/heads/main | cut -f 1 -d ' ') diff --git a/.github/workflows/execute-tests.yml b/.github/workflows/execute-tests.yml index 28836e678..634a5bc76 100644 --- a/.github/workflows/execute-tests.yml +++ b/.github/workflows/execute-tests.yml @@ -11,14 +11,17 @@ on: workpath: required: true type: string + secrets: + CODECOV_TOKEN: + required: true jobs: test: runs-on: ${{ inputs.os }} strategy: - fail-fast: false + fail-fast: true matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + python-version: ["3.10", "3.11", "3.12"] name: Python ${{ matrix.python-version }} defaults: @@ -43,7 +46,7 @@ jobs: python-version: ${{ matrix.python-version }} architecture: x64 - - uses: Gr1N/setup-poetry@v8 + - uses: Gr1N/setup-poetry@v9 - name: Check system dependencies run: make doctor @@ -67,11 +70,12 @@ jobs: current_path: ${{ inputs.workpath }} attempt_limit: 5 attempt_delay: 2000 - - name: Upload coverage - uses: codecov/codecov-action@v1 - if: ${{ inputs.os == 'ubuntu-latest' && matrix.python-version == '3.9' && github.repository == 'doorstop-dev/doorstop' }} - with: - fail_ci_if_error: true + # + # - name: Upload coverage + # uses: codecov/codecov-action@v1 + # if: ${{ inputs.os == 'ubuntu-latest' && matrix.python-version == '3.10' && github.repository == 'doorstop-dev/doorstop' }} + # with: + # fail_ci_if_error: true - name: Run checks run: make check diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..ca4f7d641 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,59 @@ +name: Codethink Doorstop Release + +on: + push: + tags: + - "v3.*" + +jobs: + tests: + uses: ./.github/workflows/execute-tests.yml + with: + os: "ubuntu-latest" + workpath: "/home/runner/work/doorstop/doorstop" + + build-and-upload: + needs: tests + name: Build and Upload + runs-on: ${{ matrix.os }} + permissions: + contents: write + strategy: + matrix: + python: ["3.10", "3.11", "3.12"] + os: + - ubuntu-latest + # - macos-latest + # - windows-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + + - uses: Gr1N/setup-poetry@v9 + + - run: poetry version ${{ github.ref_name }} + name: Set poetry version + + - name: Build wheels and sdist (tarball) + run: make dist + + - uses: actions/cache@v4 + with: + path: .venv + key: ${{ runner.os }}-poetry-${{ hashFiles('poetry.lock') }} + + - name: Create Github Release + uses: softprops/action-gh-release@v2 + if: ${{ matrix.python == '3.12' && matrix.os == 'ubuntu-latest'}} + with: + files: | + dist/*.whl + dist/*.tar.gz + tag_name: ${{ github.ref_name }} + + diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 6514a62d6..aa2319033 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -1,9 +1,13 @@ name: Linux on: - push: pull_request: - branches: [ develop ] + types: + - opened + - synchronize + - reopened + - edited + branches: [ main ] jobs: Coverage: @@ -11,8 +15,12 @@ jobs: with: os: "ubuntu-latest" workpath: "/home/runner/work/doorstop/doorstop" + if: github.event_name == 'pull_request' + Test: uses: ./.github/workflows/execute-tests.yml with: os: "ubuntu-latest" workpath: "/home/runner/work/doorstop/doorstop" + secrets: + CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}} diff --git a/.github/workflows/test-osx.yml b/.github/workflows/test-osx.yml index 0ef364b5f..5901c8835 100644 --- a/.github/workflows/test-osx.yml +++ b/.github/workflows/test-osx.yml @@ -1,13 +1,14 @@ name: macOS on: - push: pull_request: - branches: [ develop ] + branches: [ main ] jobs: Test: uses: ./.github/workflows/execute-tests.yml with: - os: "macos-latest" + os: "macos-13" workpath: "/Users/runner/work/doorstop/doorstop" + secrets: + CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}} diff --git a/.github/workflows/test-osx.yml.disabled b/.github/workflows/test-osx.yml.disabled new file mode 100644 index 000000000..400921735 --- /dev/null +++ b/.github/workflows/test-osx.yml.disabled @@ -0,0 +1,12 @@ +# name: macOS +# +# on: +# pull_request: +# branches: [ main ] +# +# jobs: +# Test: +# uses: ./.github/workflows/execute-tests.yml +# with: +# os: "macos-latest" +# workpath: "/Users/runner/work/doorstop/doorstop" diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index fdb26b214..518d78da9 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -1,9 +1,13 @@ name: Windows on: - push: pull_request: - branches: [ develop ] + types: + - opened + - synchronize + - reopened + - edited + branches: [ main ] jobs: Test: @@ -12,3 +16,5 @@ jobs: basepath: 'D:\' os: "windows-latest" workpath: 'C:\a\doorstop\doorstop' + secrets: + CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}} diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..4725358e7 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,67 @@ +# Environment variables declared in the `variables` dictionary below +# can be expanded in job definitions or before_script below +# +variables: + # Docker Images + CONTAINER_REGISTRY: "gitlab.codethink.co.uk:5000/safety/dockerfiles" + + NODE_IMAGE_ID: "d7aad9b98608971d0b5620a99290f76845269c49" + NODE_CONTAINER: "${CONTAINER_REGISTRY}/node:${NODE_IMAGE_ID}" + + DCS_CONTAINER_REGISTRY: "gitlab.codethink.co.uk:5000/safety" + DCS_CONTAINER_IMAGE_ID: "00f2e962522ecab4f1d7a3a95224ff8efd299a53" + DCS_CONTAINER: "${DCS_CONTAINER_REGISTRY}/dcs-toolchain:${DCS_CONTAINER_IMAGE_ID}" + +default: + image: "${DCS_CONTAINER}" + tags: + # Check the runners in https://gitlab.codethink.co.uk/groups/codethink/-/wikis/Internal-Gitlab-Runners + - sml.amd64 + before_script: + - pip install poetry + - make install + +# +# Declare the stages +# +stages: + - lint + - test + - build +# +# Workflow rules for controlling when pipelines are created. +# For more details see https://docs.gitlab.com/ee/ci/yaml/workflow.html +# +workflow: + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_PIPELINE_SOURCE == "web" + - if: $CI_PIPELINE_SOURCE == "schedule" + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + +########################################################### +# Lint stage jobs # +########################################################### + +# +# General yaml linter, this recursively detects malformed YAML +# +lint-doorstop: + stage: lint + script: + - make check +# +# Validate the markdown for invalid links, using markdown-link-check, see: +# +# https://github.com/tcort/markdown-link-check +# +test-doorstop: + stage: test + needs: [lint-doorstop] + script: + - make test + +build-doorstop: + stage: build + script: + - make dist diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..f4ce3cc22 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,12 @@ +exclude: ^(doorstop|docs)/.* + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-yaml + - repo: https://gitlab.codethink.co.uk/lorry-mirrors/github/doorstop-dev/doorstop + rev: codethink-tag-3.0b11 + hooks: + - id: check-doorstop-errors + - id: check-unreviewed-items diff --git a/.pylint.ini b/.pylint.ini index 18ae00d76..16f2c3c24 100644 --- a/.pylint.ini +++ b/.pylint.ini @@ -419,4 +419,4 @@ known-third-party=enchant # Exceptions that will emit a warning when being caught. Defaults to # "Exception" -overgeneral-exceptions=Exception +overgeneral-exceptions=builtins.Exception diff --git a/.readthedocs.yaml b/.readthedocs.yaml index c6e81f3ea..0807bef7b 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -3,11 +3,11 @@ version: 2 build: os: ubuntu-22.04 tools: - python: "3.8" + python: "3.9" mkdocs: configuration: mkdocs.yml python: install: - - requirements: docs/requirements.txt + - requirements: docs/requirements.txt diff --git a/.tool-versions b/.tool-versions index af9b62eb8..92c757d5c 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1,2 @@ -python 3.8.13 +python 3.9.17 poetry 1.7.1 diff --git a/.verchew.ini b/.verchew.ini index 4ef10eb1b..9832f36a6 100644 --- a/.verchew.ini +++ b/.verchew.ini @@ -6,7 +6,7 @@ version = GNU Make [Python] cli = python -version = 3.8 || 3.9 || 3.10 || 3.11 || 3.12 +version = 3.9 || 3.10 || 3.11 || 3.12 [Poetry] @@ -17,6 +17,6 @@ version = 1.7 cli = dot cli_version_arg = -V -version = 9 +version = 9 || 10 optional = true message = This is only needed to generate UML diagrams for documentation. diff --git a/.vscode/settings.json b/.vscode/settings.json index 2df7075b6..54c825fc8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,12 +13,9 @@ "prof/": true, "site/": true, }, - "python.linting.enabled": true, - "python.linting.pylintEnabled": true, - "python.linting.pylintArgs": ["--rcfile", ".pylint.ini"], - "python.linting.mypyEnabled": true, - "python.linting.mypyArgs": ["--config-file", ".mypy.ini"], - "python.linting.pydocstyleEnabled": true, + "python.defaultInterpreterPath": ".venv/bin/python", + "pylint.args": ["--rcfile=.pylint.ini"], + "editor.formatOnSave": true, "cSpell.words": [ "Autobuild", "basepath", diff --git a/CHANGELOG.md b/CHANGELOG.md index 32a09392d..35a15ce65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,18 @@ +# 3.0 (beta) Codethink 0.2 + +- Allow references to hidden file paths +- Bump package versions to address security issues + +# 3.0 (beta) Codethink 0.1 + +- Add publish support for AsciiDoc output +- Ability to define settings through `.doorstoprc.py` +- Support for mkdocs-flavoured markdown +- Dropped support to python 3.9 + # 3.0 (beta) -- **BREAKING:** Dropped support for Python 3.6 and 3.7. +- **BREAKING:** Dropped support for Python 3.6, 3.7, and 3.8. - **BREAKING:** Removed `--no-body-levels` option to `doorstop publish`. - Fixed overriding default attributes with `doorstop add`. ([@tangoalx](https://github.com/doorstop-dev/doorstop/pull/544)) - Fixed encoding error with special characters on Windows. ([@urbasus](https://github.com/doorstop-dev/doorstop/pull/526)) diff --git a/README.md b/README.md index adb663e2d..93582afe3 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Additional references: ## Requirements -- Python 3.8+ +- Python 3.9+ - A version control system for requirements storage ## Installation diff --git a/docs/api/scripting.md b/docs/api/scripting.md index 704f5972f..fc5d92a37 100644 --- a/docs/api/scripting.md +++ b/docs/api/scripting.md @@ -72,3 +72,39 @@ if __name__ == '__main__': ``` Both `document_hook` and `item_hook` are optional, but if provided these callbacks will be passed each corresponding instance. Each callback should yield instances of Doorstop's exception classes based on severity of the issue. + +## Validation Hook per folder + +Doorstop also has an extension which allows creating an item validation per folder, allowing the document to have different validations for each document section. +To enable this mechanism you must insert into your `.doorstop.yml` file the following lines: + +```yaml +extensions: + item_validator: .req_sha_item_validator.py # a python file path relative to .doorstop.yml +``` + +or + +```yaml +extensions: + item_validator: ../validators/my_complex_validator.py # a python file path relative to .doorstop.yml +``` + +The referenced file must have a function called `item_validator` with a single parameter `item`. + +Example: + +```python + + +def item_validator(item): + if getattr(item, "references") == None: + return [] # early return + for ref in item.references: + if ref['sha'] != item._hash_reference(ref['path']): + yield DoorstopError("Hash has changed and it was not reviewed properly") + +``` + +Although it is not required, it is recommended to yield a Doorstop type such as, +`DoorstopInfo`, `DoorstopError`, or `DoorstopWarning`. diff --git a/docs/reference/document.md b/docs/reference/document.md index 90bde32f8..c0bc1d307 100644 --- a/docs/reference/document.md +++ b/docs/reference/document.md @@ -103,4 +103,28 @@ In `path/to/file.yml`: Some template text, which may have several lines. -``` \ No newline at end of file +``` +# Beta Features + +## External documents + +**Note: When you use this feature, it is designed assuming that the external parent will be responsible for identifying the root document.** + +It is possible to attach an external parent document (in other words an external git repo) as a parent to a local document. + +The objective of this feature is to allow reusability of previous documents or even to split the work across multiple +repos. + +To use this feature you need to modify `.doorstop.yml` to be similar to: + +```yaml +external_parent: <-- git url to used to pull the external parent **Required** +external_parent_tag: <-- tag or branch to be used **REQUIRED** +settings: + parent: REQ <---- PREFIX from the external document **REQUIRED** + digits: 3 + prefix: REQ + sep: '' +``` + +If you need to update the external tag or parent location, run doorstop with the flag `--clean-external-docs`. \ No newline at end of file diff --git a/docs/reference/item.md b/docs/reference/item.md index adb6b5c88..5f5a79e2e 100644 --- a/docs/reference/item.md +++ b/docs/reference/item.md @@ -243,10 +243,47 @@ of the item. ```yaml references: -- path: tests/test1.cpp - type: file -- path: tests/test2.cpp - type: file + - path: tests/test1.cpp + type: file + - path: tests/test2.cpp + type: file +``` + +### Generating hash for referenced files + +Doorstop has an extension to generate a hash for each referenced file inside the array. + +.doorstop.yml + +```yaml +settings: + digits: 3 + prefix: REQ + sep: "" +extensions: + item_sha_required: true +``` + +Now when reviewing items, Doorstop will insert a field named `sha` where each item reference will +contain a `sha256`. + +Example: + +```yaml +active: true +derived: false +header: "" +level: 2.0 +links: [] +normative: true +ref: "" +references: + - path: files/a.file + sha: 28c16553011a46bca9b78d189f8fd30c59c4138a1b6a9a4961f525849d48037e + type: file +reviewed: BU95pdUUcz5DrFur8GUUqBaIXSNPBYMEZVMy-6IPM4s= +text: | + My text ``` ### Note: new behavior vs old behavior diff --git a/doorstop/cli/commands.py b/doorstop/cli/commands.py index 1df175318..6b6bd1c16 100644 --- a/doorstop/cli/commands.py +++ b/doorstop/cli/commands.py @@ -420,6 +420,8 @@ def run_review(args, cwd, error, catch=True): for item in _iter_items(args, tree, error): utilities.show("marking item {} as reviewed...".format(item.uid)) item.review() + if item.references: + assert isinstance(item.find_references(), list) if not success: return False @@ -513,14 +515,21 @@ def run_export(args, cwd, error, catch=True, auto=False, _tree=None): # Write to output file(s) if args.path: + # This only executes if success context returns something that + # can be classified as true and document is access only when whole tree is **False**, + # it safe to ignore the warning regarding document due to this. + # pylint: disable=E0606 + if whole_tree: msg = "exporting tree to '{}'...".format(args.path) utilities.show(msg, flush=True) path = exporter.export(tree, args.path, ext, auto=auto) + else: msg = "exporting document {} to '{}'...".format(document, args.path) utilities.show(msg, flush=True) path = exporter.export(document, args.path, ext, auto=auto) + if path: utilities.show("exported: {}".format(path)) @@ -563,6 +572,11 @@ def run_publish(args, cwd, error, catch=True): # Write to output file(s) if args.path: + # This only executes if success context returns something that + # can be classified as true and document is access only when whole tree is **False**, + # it safe to ignore the warning regarding document due to this. + # pylint: disable=E0606 + path = os.path.abspath(os.path.join(cwd, args.path)) if whole_tree: msg = "publishing tree to '{}'...".format(path) @@ -665,12 +679,10 @@ def _iter_items(args, tree, error): if item: yield item elif document: - for item in document: - yield item + yield from document else: for document in tree: - for item in document: - yield item + yield from document def _export_import(args, cwd, error, document, ext): diff --git a/doorstop/cli/main.py b/doorstop/cli/main.py index 5b92b7c1a..56e8fc47f 100644 --- a/doorstop/cli/main.py +++ b/doorstop/cli/main.py @@ -7,6 +7,9 @@ import argparse import os import sys +from pathlib import Path +from shutil import rmtree +from types import ModuleType from doorstop import common, settings from doorstop.cli import commands, utilities @@ -17,6 +20,18 @@ EDITOR = os.environ.get("EDITOR") +def findrc_file() -> Path | None: + cwd = Path.cwd() + doorstoprc = cwd / ".doorstoprc.py" + return doorstoprc if doorstoprc.is_file() else None + + +def clean_external() -> None: + external = Path.cwd() / ".doorstop-external" + if external.exists(): + rmtree(external, ignore_errors=True) + + def main(args=None): # pylint: disable=R0915 """Process command-line arguments and run the program.""" from doorstop import CLI, DESCRIPTION, VERSION @@ -49,6 +64,15 @@ def main(args=None): # pylint: disable=R0915 help="use a custom port for the server", default=settings.SERVER_PORT, ) + + server.add_argument( + "--settings", + metavar="SETTINGS_FILE.py", + help="""Use a doorstop settings file instead of options arguments + NOTE: doorstop will ignore options passed from the cli""", + default=None, + type=str, + ) server.add_argument( "-f", "--force", @@ -145,6 +169,12 @@ def main(args=None): # pylint: disable=R0915 action="store_true", help="display all warning-level issues as errors", ) + parser.add_argument( + "--clean-external-docs", + dest="clean_ext_docs", + action="store_true", + help="Clean external documents before running any command", + ) # Build sub-parsers subs = parser.add_subparsers(help="", dest="command", metavar="") @@ -164,12 +194,35 @@ def main(args=None): # pylint: disable=R0915 # Parse arguments args = parser.parse_args(args=args) - # Configure logging utilities.configure_logging(args.verbose) + if args.clean_ext_docs: + log.info("Deleting .doorstop-external folder") + clean_external() + # Configure settings - utilities.configure_settings(args) + run_settings = args.settings or findrc_file() + if run_settings: + run_settings = ( + Path(run_settings) if isinstance(run_settings, str) else run_settings + ) + log.debug(f"Loading settings from: {run_settings}") + file_settings = common.import_path_as_module(run_settings) + # get overridden settings list + custom_settings = ( + x + for x in dir(file_settings) + if not x.startswith("_") + and not isinstance(getattr(file_settings, x), ModuleType) + ) + for i in custom_settings: + # if they are valid set them + if hasattr(settings, i): + setattr(settings, i, getattr(file_settings, i)) + else: + log.debug("Loading default settings") + utilities.configure_settings(args) # Run the program function = commands.get(args.command) @@ -515,6 +568,7 @@ def _publish(subs, shared): "path", nargs="?", help="path to published file or directory for 'all'" ) group = sub.add_mutually_exclusive_group() + group.add_argument("-a", "--asciidoc", action="store_true", help="output AsciiDoc") group.add_argument( "-t", "--text", action="store_true", help="output text (default when no path)" ) diff --git a/doorstop/cli/tests/test_all.py b/doorstop/cli/tests/test_all.py index 4728d5d60..053aabfe8 100644 --- a/doorstop/cli/tests/test_all.py +++ b/doorstop/cli/tests/test_all.py @@ -24,7 +24,7 @@ from doorstop.core.tests.helpers import on_error_with_retry REQ_COUNT = 23 -ALL_COUNT = 55 +ALL_COUNT = 57 class TempTestCase(unittest.TestCase): @@ -37,6 +37,9 @@ def setUp(self): def tearDown(self): os.chdir(self.cwd) if os.path.exists(self.temp): + + # until we only support 3.12+ ignore this, as we need to move to onexc instead of onerror + # pylint: disable=W4903 shutil.rmtree(self.temp, onerror=on_error_with_retry) @@ -63,6 +66,8 @@ def setUp(self): def tearDown(self): super().tearDown() os.chdir(self.cwd) + # until we only support 3.12+ ignore this, as we need to move to onexc instead of onerror + # pylint: disable=W4903 shutil.rmtree(self.temp, onerror=on_error_with_retry) def test_main(self): @@ -789,6 +794,16 @@ def test_publish_document_markdown_file(self): self.assertIs(None, main(["publish", "req", path])) self.assertTrue(os.path.isfile(path)) + def test_publish_document_asciidoc(self): + """Verify 'doorstop publish' can create AsciiDoc output.""" + self.assertIs(None, main(["publish", "req", "--asciidoc"])) + + def test_publish_document_asciidoc_file(self): + """Verify 'doorstop publish' can create an AsciiDoc file.""" + path = os.path.join(self.temp, "req.adoc") + self.assertIs(None, main(["publish", "req", path])) + self.assertTrue(os.path.isfile(path)) + def test_publish_document_html_file(self): """Verify 'doorstop publish' can create an HTML file.""" path = os.path.join(self.temp, "req.html") diff --git a/doorstop/cli/utilities.py b/doorstop/cli/utilities.py index 6df48bb9a..6ecce61fe 100644 --- a/doorstop/cli/utilities.py +++ b/doorstop/cli/utilities.py @@ -182,6 +182,7 @@ def get_ext(args, error, ext_stdout, ext_file, whole_tree=False): ".csv": "csv", ".xlsx": "xlsx", ".tex": "latex", + ".adoc": "asciidoc", }.items(): try: if getattr(args, option): diff --git a/doorstop/common.py b/doorstop/common.py index 19111e165..a32259161 100644 --- a/doorstop/common.py +++ b/doorstop/common.py @@ -11,6 +11,12 @@ import os import re import shutil +from importlib.abc import Loader +from importlib.machinery import ModuleSpec +from importlib.util import module_from_spec, spec_from_file_location +from pathlib import Path +from types import ModuleType +from typing import Union, cast import frontmatter import yaml @@ -101,8 +107,7 @@ def read_lines(path, encoding="utf-8"): """ log.trace("reading lines from '{}'...".format(path)) # type: ignore with open(path, "r", encoding=encoding) as stream: - for line in stream: - yield line + yield from stream def read_text(path): @@ -345,4 +350,15 @@ def dump_markdown(data, textattr): text = frontmatter.dumps( frontmatter.Post(content, **data), Dumper=yaml.dumper.Dumper ) + if text[-1] != "\n": + text += "\n" return text + + +def import_path_as_module(path: Union[Path, str]) -> ModuleType: + name = Path(path).stem + spec = cast(ModuleSpec, spec_from_file_location(name, path)) + module = cast(ModuleType, module_from_spec(spec)) + loader = cast(Loader, spec.loader) + loader.exec_module(module) + return module diff --git a/doorstop/core/builder.py b/doorstop/core/builder.py index 5669061d3..67e09a35b 100644 --- a/doorstop/core/builder.py +++ b/doorstop/core/builder.py @@ -2,8 +2,14 @@ """Functions to build a tree and access documents and items.""" + import os -from typing import List, Optional +from collections.abc import Mapping +from pathlib import Path +from traceback import format_exception + +from dulwich import porcelain +from dulwich.repo import Repo from doorstop import common from doorstop.common import DoorstopError @@ -12,7 +18,7 @@ from doorstop.core.tree import Tree log = common.logger(__name__) -_tree: Optional[Tree] = None # implicit tree for convenience functions +_tree: Tree | None = None # implicit tree for convenience functions def build(cwd=None, root=None, request_next_number=None) -> Tree: @@ -28,17 +34,26 @@ def build(cwd=None, root=None, request_next_number=None) -> Tree: :return: new :class:`~doorstop.core.tree.Tree` """ - documents: List[Document] = [] + + documents: list[Document] = [] # Find the root of the working copy cwd = cwd or os.getcwd() root = root or vcs.find_root(cwd) + # external parents inclusion + external_documents: dict[str, str] = {} # Prefix, tag + external_base_path: Path | None = ( + Path(root, ".doorstop-external") or None + ) # TODO: make this configurable + # Find all documents in the working copy log.info("looking for documents in {}...".format(root)) skip_file_name = ".doorstop.skip-all" if not os.path.isfile(os.path.join(root, skip_file_name)): - _document_from_path(root, root, documents) + _document_from_path( + root, root, documents, external_documents, external_base_path + ) exclude_dirnames = {".git", ".venv", "venv"} if not os.path.isfile(os.path.join(root, skip_file_name)): for dirpath, dirnames, _ in os.walk(root, topdown=True): @@ -50,12 +65,18 @@ def build(cwd=None, root=None, request_next_number=None) -> Tree: if os.path.isfile(os.path.join(path, skip_file_name)): continue whilelist_dirnames.append(dirname) - _document_from_path(path, root, documents) + _document_from_path( + path, root, documents, external_documents, external_base_path + ) dirnames[:] = whilelist_dirnames # Build the tree if not documents: log.info("no documents found in: {}".format(root)) + + for document in documents: + log.info("found document: {}".format(document)) + log.info("building tree...") tree = Tree.from_list(documents, root=root) tree.request_next_number = request_next_number @@ -66,14 +87,26 @@ def build(cwd=None, root=None, request_next_number=None) -> Tree: return tree -def _document_from_path(path, root, documents): +def _check_for_duplicates(documents: list[Document], document: Document): + if not any(docs.prefix == document.prefix for docs in documents): + documents.append(document) + + +def _document_from_path( + path, + root, + documents: list[Document], + external_documents: dict[str, str], + external_base_path: Path | None, +): """Attempt to create and append a document from the specified path. :param path: path to a potential document :param root: path to root of working copy :param documents: list of :class:`~doorstop.core.document.Document` to append results - + :param external_documents: dictionary to control the version of external documents + :param external_base_path: where external documents will be stored """ try: document = Document(path, root, tree=None) # tree attached later @@ -83,8 +116,33 @@ def _document_from_path(path, root, documents): if document.skip: log.debug("skipped document: {}".format(document)) else: - log.info("found document: {}".format(document)) - documents.append(document) + document.load() # force to load the properties Earlier + if ( + document.external_parent and document.external_parent_tag + ) and external_base_path: + if not getattr(document, "parent"): + raise DoorstopError( + "Document {} @ {} have external parent configs and it doesn't have a parent prefix".format( + document.prefix, document.path + ) + ) + log.debug( + """Document has external parent +external information: + external Parent: {} + external Tag: {}""".format( + document.external_parent, document.external_parent_tag + ) + ) + + _download_external_parent( + external_base_path, + document.external_parent, + document.external_parent_tag, + documents, + external_documents, + ) + _check_for_duplicates(documents, document) def find_document(prefix): @@ -120,3 +178,165 @@ def _clear_tree(): """Force the shared tree to be rebuilt.""" global _tree _tree = None + + +def _create_external_dir(external_base_path: Path): + """Create the folder that will store pulled documents.""" + match external_base_path.exists(): + case True: + log.debug( + "Skipping creation folder already exists {} in {}.".format( + external_base_path.parts[-1], external_base_path.parent + ) + ) + case False: + log.info( + "Creating folder {} in {}".format( + external_base_path.parts[-1], external_base_path.parent + ) + ) + try: + external_base_path.mkdir(exist_ok=True) + except Exception as e: + tb_str = "".join(format_exception(None, e, e.__traceback__)) + raise DoorstopError( + """Something unexpected has happened when trying to create folder {} in {}\n. + Details: {}""".format( + external_base_path.parent, external_base_path.parts[-1], tb_str + ) + ) + + +def _external_documents_check( + existing_external_docs: Mapping[str, str], new_external_docs: Mapping[str, str] +): + results: dict[str, bool] = {} + + for key in new_external_docs.keys(): + if key in existing_external_docs: + results[key] = existing_external_docs[key] == new_external_docs[key] + + if list(results.values()).count(False) >= 1: + raise DoorstopError( + f""" +Different version for a prefix detected please check the external document definitions. +Affected prefix(es) { [ x for x,v in results.items() if v is False ] } + """ + ) + + +def _validate_external_documents( + new_external_doc: Path, + external_document_tag: str, + external_documents: dict[str, str], + doorstop_documents: list[Document], +): + """ + Reponsible to discover external documents and add them to the doorstop main document list. + + :param new_external_doc: path to a potential external document + :param external_document_tag: tag to track which version of the document we are using + :param external_documents: dictionary to control the version of external documents format is Document Prefix: Tag (version value) + :param doorstop_documents: list of :class:`~doorstop.core.document.Document` to append results + """ + + def find_external_docs(external_path: Path): + """Reproduction partial builder's logic here for external docs.""" + root = new_external_doc.absolute().parent + external_docs: list[Document] = [] + skip_file_name = ".doorstop.skip-all" + exclude_dirnames = {".git", ".venv", "venv"} + # case git root is a document + if not os.path.isfile(os.path.join(root, skip_file_name)): + _document_from_path( + external_path, external_path, external_docs, external_documents, root + ) + + # search through folders + for dirpath, dirnames, _ in os.walk(external_path, topdown=True): + for dirname in dirnames: + if dirname in exclude_dirnames: + continue + path = os.path.join(dirpath, dirname) + if os.path.isfile(os.path.join(path, skip_file_name)): + continue + _document_from_path( + path, path, external_docs, external_documents, external_path + ) + return external_docs + + new_external_docs = find_external_docs(new_external_doc) + entries = {str(d.prefix): external_document_tag for d in new_external_docs} + _external_documents_check(external_documents, entries) + # external_documents.update({k:v for k,v in entries.items() if k not in external_documents.keys()}) #TODO: is it really necessary to filter? + external_documents.update(entries) # for now lets just throw the whole dict + + for nrd in new_external_docs: + _check_for_duplicates(doorstop_documents, nrd) + + +def _git_pull(git_url: str, git_tag: str, target_folder: Path): + + def exact_want(refs, _depth=None): + tag = ( + b"refs/heads/" + git_tag.encode() + if git_tag in ["main", "master"] + else b"refs/tags/" + git_tag.encode() + ) + if tag in refs: + return tag + + raise DoorstopError("ref {} not found in external {}".format(git_tag, git_url)) + + path = str(target_folder.absolute()) + with open(os.devnull, "wb") as f: + if not (target_folder / ".git").exists(): + Repo.init(path, mkdir=False) + porcelain.pull( + path, + git_url, + refspecs=exact_want( + porcelain.fetch(path, git_url, errstream=f, outstream=f) + ), + errstream=f, + outstream=f, + force=True, + report_activity=None, + ) + + +def _download_external_parent( + external_base_path: Path, + external_parent_url: str, + external_parent_tag: str, + doorstop_documents: list[Document], + external_documents: dict[str, str], +): + + _create_external_dir(external_base_path) + + folder_name = external_parent_url.split("/")[-1].split(".")[0] + + if not folder_name: + raise DoorstopError( + "Couldn't guess a name to storage external parent, check the config for {}".format( + external_parent_url + ) + ) + + try: + target = external_base_path / folder_name + _create_external_dir(target) + _git_pull(external_parent_url, external_parent_tag, target) + _validate_external_documents( + target, external_parent_tag, external_documents, doorstop_documents + ) + except Exception as e: + tb_str = "".join(format_exception(None, e, e.__traceback__)) + raise DoorstopError( + """Unexpected error when downloading external parent from {} +ERROR Details: + {} """.format( + external_parent_url, tb_str + ) + ) diff --git a/doorstop/core/document.py b/doorstop/core/document.py index 9c996340a..ba6393354 100644 --- a/doorstop/core/document.py +++ b/doorstop/core/document.py @@ -6,12 +6,18 @@ import re from collections import OrderedDict from itertools import chain -from typing import Dict, List +from typing import Any, Dict, List +from pathlib import Path import yaml from doorstop import common, settings -from doorstop.common import DoorstopError, DoorstopInfo, DoorstopWarning +from doorstop.common import ( + DoorstopError, + DoorstopInfo, + DoorstopWarning, + import_path_as_module, +) from doorstop.core.base import ( BaseFileObject, BaseValidatable, @@ -68,13 +74,18 @@ def __init__(self, path, root=os.getcwd(), **kwargs): self._data["parent"] = None # type: ignore self._data["itemformat"] = kwargs.get("itemformat") # type: ignore self._extended_reviewed: List[str] = [] + self.extensions: Dict[str, Any] = {} self._items: List[Item] = [] self._itered = False self.children: List[Document] = [] + self.external_parent: str | None = None + self.external_parent_tag: str | None = None if not self._data["itemformat"]: self._data["itemformat"] = Item.DEFAULT_ITEMFORMAT + self.extensions = None + def __repr__(self): return "Document('{}')".format(self.path) @@ -228,6 +239,11 @@ def load(self, reload=False): key, self.config ) raise DoorstopError(msg) + + self.extensions = data.get("extensions", {}) + self.external_parent = data.get("external_parent", None) + self.external_parent_tag = data.get("external_parent_tag", None) + # Set meta attributes self._loaded = True if reload: @@ -759,6 +775,11 @@ def _reorder_automatic(items, start=None, keep=None): # Save the current level as the previous level plevel = clevel.copy() + @staticmethod + def _import_validator(path: str): + """Load an external python item validator logic from doorstop yml defined for the folder.""" + return import_path_as_module(path) + @staticmethod def _items_by_level(items, keep=None): """Iterate through items by level with the kept item first.""" @@ -816,6 +837,15 @@ def get_issues( """ assert document_hook is None skip = [] if skip is None else skip + + ext_validator = None + if "item_validator" in self.extensions: # type: ignore + validator = self.extensions["item_validator"] # type: ignore + path = os.path.join(self.path, validator) # type: ignore + ext_validator = self._import_validator(path) + ext_validator = getattr(ext_validator, "item_validator") + + extension_validator = ext_validator if ext_validator else lambda **kwargs: [] hook = item_hook if item_hook else lambda **kwargs: [] if self.prefix in skip: @@ -844,6 +874,7 @@ def get_issues( for issue in chain( hook(item=item, document=self, tree=self.tree), item_validator.get_issues(item, skip=skip), + extension_validator(item=item), ): # Prepend the item's UID to yielded exceptions if isinstance(issue, Exception): diff --git a/doorstop/core/editor.py b/doorstop/core/editor.py index 6dbdde0d9..79299dd64 100644 --- a/doorstop/core/editor.py +++ b/doorstop/core/editor.py @@ -3,11 +3,11 @@ """Functions to edit documents and items.""" import os +import shutil import subprocess import sys import tempfile import time -from distutils.spawn import find_executable from doorstop import common from doorstop.common import DoorstopError @@ -82,12 +82,13 @@ def launch(path, tool=None): """ # Determine how to launch the editor + args = ["Non-valid-editor"] # place holder, if everything fails if tool: args = [tool, path] elif sys.platform.startswith("darwin"): args = ["open", path] elif os.name == "nt": - cygstart = find_executable("cygstart") + cygstart = shutil.which("cygstart") if cygstart: args = [cygstart, path] else: diff --git a/doorstop/core/importer.py b/doorstop/core/importer.py index 87fa7a95b..adbc470e8 100644 --- a/doorstop/core/importer.py +++ b/doorstop/core/importer.py @@ -266,7 +266,7 @@ def _itemize(header, data, document, mapping=None): ref_dict = {"type": ref_type, "path": ref_path} if len(ref_item_components) == 3: - ref_keyword = ref_item_components[2].split(":")[1] + ref_keyword = ref_item_components[2].split(":", 1)[1] ref_dict["keyword"] = ref_keyword ref.append(ref_dict) diff --git a/doorstop/core/item.py b/doorstop/core/item.py index 04aae6971..fce0d0d09 100644 --- a/doorstop/core/item.py +++ b/doorstop/core/item.py @@ -3,8 +3,10 @@ """Representation of an item in a document.""" import functools +import hashlib import linecache import os +from pathlib import Path from typing import Any, List from doorstop import common, settings @@ -257,13 +259,18 @@ def _set_attributes(self, attributes): stripped_value = [] for ref_dict in value: ref_type = ref_dict["type"] - ref_path = ref_dict["path"] + ref_path = ( + ref_dict["path"] + if ".doorstop-external" not in self.path # type: ignore + else str(Path(self.root) / ref_dict["path"]) + ) stripped_ref_dict = {"type": ref_type, "path": ref_path.strip()} if "keyword" in ref_dict: ref_keyword = ref_dict["keyword"] stripped_ref_dict["keyword"] = ref_keyword - + if "sha" in ref_dict: + stripped_ref_dict["sha"] = ref_dict["sha"] stripped_value.append(stripped_ref_dict) value = stripped_value @@ -297,6 +304,37 @@ def load(self, reload=False): # Set meta attributes self._loaded = True + def _hash_reference(self, path): + """ + Extension method created to generate checksum from the list of find_references. + + :param path: a path from a reference inside the references list + """ + sha = None + if "item_sha_required" not in self.document.extensions: + return sha + + try: + sha256 = hashlib.sha256() + with open(os.path.join(self.root, path), "rb") as f: + BUFSIZE = ( + int(self.document.extensions["item_sha_buffer_size"]) + if "item_sha_buffer_size" in self.document.extensions + else 65536 + ) + while True: + fdata = f.read(BUFSIZE) + if not fdata: + break + sha256.update(fdata) + sha = sha256.hexdigest() + + # We don't report missing files because validate already does that. + except FileNotFoundError: + pass + + return sha + @edit_item def save(self): """Format and save the item's properties to its file.""" @@ -363,6 +401,8 @@ def _yaml_data(self, textattributekeys=None): if "keyword" in el: ref_dict["keyword"] = el["keyword"] # type: ignore + if "sha" in el: + ref_dict["sha"] = el["sha"] # type: ignore stripped_value.append(ref_dict) value = stripped_value # type: ignore @@ -852,6 +892,30 @@ def clear(self, parents=None): def review(self): """Mark the item as reviewed.""" log.info("marking item as reviewed...") + + # only introduce the sha for reference files if + # the option item_sha_required is defined in the extension section from .doorstop.yml + if ( + "item_sha_required" in self.document.extensions + and self.references is not None + ): + references = self.references + for ref, _ in enumerate(references): + temp_sha = self._hash_reference(references[ref]["path"]) + log.info(references[ref]) + if "sha" in references[ref] and references[ref]["sha"] == temp_sha: + log.info( + f"{references[ref]['path']} checksum did not change skipping update..." + ) + continue + + if "sha" in references[ref] and references[ref]["sha"] != temp_sha: + log.info(f"updating checksum for {references[ref]['path']}") + references[ref]["sha"] = temp_sha + else: + log.info(f"Inserting checksum for {references[ref]['path']}") + references[ref]["sha"] = temp_sha + self._data["reviewed"] = self.stamp(links=True) @delete_item diff --git a/doorstop/core/publisher.py b/doorstop/core/publisher.py index 298ac6339..bbbe82163 100644 --- a/doorstop/core/publisher.py +++ b/doorstop/core/publisher.py @@ -6,6 +6,7 @@ from doorstop import common, settings from doorstop.common import DoorstopError +from doorstop.core.publishers.asciidoc import AsciiDocPublisher from doorstop.core.publishers.html import HtmlPublisher from doorstop.core.publishers.latex import LaTeXPublisher from doorstop.core.publishers.markdown import MarkdownPublisher @@ -133,6 +134,7 @@ def check(ext, obj=None): PUBLISHER_LIST = { ".txt": TextPublisher(obj, ext), ".md": MarkdownPublisher(obj, ext), + ".adoc": AsciiDocPublisher(obj, ext), ".html": HtmlPublisher(obj, ext), ".tex": LaTeXPublisher(obj, ext), } diff --git a/doorstop/core/publishers/asciidoc.py b/doorstop/core/publishers/asciidoc.py new file mode 100644 index 000000000..13cf8d480 --- /dev/null +++ b/doorstop/core/publishers/asciidoc.py @@ -0,0 +1,283 @@ +# SPDX-License-Identifier: LGPL-3.0-only + +"""Functions to publish documents and items in AsciiDoc.""" + +import os +import shutil +from pathlib import Path + +from doorstop import common, settings +from doorstop.core.publishers.base import BasePublisher, format_level +from doorstop.core.publishers.markdown import clean_link +from doorstop.core.types import is_item, iter_items + +log = common.logger(__name__) + + +class AsciiDocPublisher(BasePublisher): + """AsciiDoc publisher.""" + + def __init__(self, obj, ext): + super().__init__(obj, ext) + + # Per-document overrides + # These are off by default, but can be enabled by including the indicated + # reference in a document's attributes: publish section + + self.levels = False # document.publish["asciidoc_levels"] + self.toc = False # document.publish["asciidoc_toc"] + self.references = False # document.publish["asciidoc_references"] + + # Output directory for the publish action + self.directory = None + + def publishAction(self, document, path): + """Publish action.""" + super().publishAction(document, path) + + # Store output directory for the publish action + self.directory = Path(path).parent + + # This function is called per document, so we need to set these + # back to the default (False) before checking the config for + # the current document + self.levels = False + self.toc = False + self.references = False + + if document.publish: + for attr in document.publish: + if attr == "asciidoc_levels": + self.levels = True + elif attr == "asciidoc_toc": + self.toc = True + if attr == "asciidoc_references": + self.references = True + + def create_index(self, directory, index=None, extensions=(".adoc",), tree=None): + """No index for AsciiDoc.""" + + def create_matrix(self, directory): + """No traceability matrix for AsciiDoc.""" + + def format_attr_list(self, item, linkify): + """Create a AsciiDoc attribute list for a heading.""" + link = clean_link("{u}".format(u=item.uid)) + return "[[{l}]]\n".format(l=link) if linkify else "" + + def format_ref(self, item): + """Format an external reference in AsciiDoc.""" + if settings.CHECK_REF: + path, line = item.find_ref() + path = Path(path) + if line: + return "> `{p}` (line {line})".format(p=path, line=line) + else: + return "> `{p}`".format(p=path) + else: + return "> '{r}'".format(r=item.ref) + + def format_references(self, item): + """Format an external reference in AsciiDoc.""" + if settings.CHECK_REF: + references = item.find_references() + text_refs = [] + for ref_item in references: + path, line = ref_item + path = Path(path) + + # If 'asciidoc_references' option is enabled for document and referenced file + # is an AsciiDoc source file, then include the content in the output + if self.references and path.suffix == ".adoc": + self.copy_reference(path) + text_refs.append("") + text_refs.append("---") + text_refs.append("include::{p}[]".format(p=path)) + text_refs.append("") + text_refs.append("---") + elif line: + text_refs.append("> `{p}` (line {line})".format(p=path, line=line)) + else: + text_refs.append("> `{p}`".format(p=path)) + + return "\n".join(ref for ref in text_refs) + else: + references = item.references + text_refs = [] + for ref_item in references: + path = ref_item["path"] + path = Path(path) + + # If 'asciidoc_references' option is enabled for document and referenced file + # is an AsciiDoc source file, then include the content in the output + if self.references and path.suffix == ".adoc": + self.copy_reference(path) + text_refs.append("include::{p}[]".format(p=path)) + else: + text_refs.append("> '{r}'".format(r=path)) + return "\n".join(ref for ref in text_refs) + + def format_links(self, items, linkify): + """Format a list of linked items in AsciiDoc.""" + links = [] + for item in items: + link = self.format_item_link(item, linkify=linkify) + links.append(link) + return ", ".join(links) + + def format_item_link(self, item, linkify=True): + """Format an item link in AsciiDoc.""" + if linkify and is_item(item): + link = clean_link("{u}".format(u=item.uid)) + if item.header: + return "xref:{p}.adoc#{l}[{u} {h}]".format( + u=item.uid, l=link, h=item.header, p=item.document.prefix + ) + return "xref:{p}.adoc#{l}[{u}]".format( + u=item.uid, l=link, p=item.document.prefix + ) + else: + return str(item.uid) # if not `Item`, assume this is an `UnknownItem` + + def format_label_links(self, label, links, linkify): + """Join a string of label and links with formatting.""" + if linkify: + return "_{lb}_ {ls}".format(lb=label, ls=links) + else: + return "_{lb}_ {ls}".format(lb=label, ls=links) + + def table_of_contents(self, linkify=None, obj=None): + """Generate a table of contents for an AsciiDoc document.""" + toc = ":toc:\n" + return toc + + def lines(self, obj, **kwargs): + """Yield lines for a AsciiDoc report. + + :param obj: Item, list of Items, or Document to publish + :param linkify: turn links into hyperlinks + + :return: iterator of lines of text + + """ + linkify = kwargs.get("linkify", False) + toc = kwargs.get("toc", False) + if self.toc and toc: + yield self.table_of_contents(linkify=linkify, obj=obj) + + yield from self._lines_asciidoc(obj, **kwargs) + + def _generate_heading_from_item(self, item): + """Generate a heading from an item in a consistent way for AsciiDoc. + + This ensures that references between documents are consistent. + """ + result = "" + + # Start at level 2 (==), because level 1 (=) is the document title + heading = "=" * (item.depth + 1) + level = format_level(item.level) + if item.heading: + text_lines = item.text.splitlines() + if item.header: + text_lines.insert(0, item.header) + # Level and Text + if self.levels and settings.PUBLISH_HEADING_LEVELS: + standard = "{h} {lev} {t}".format( + h=heading, lev=level, t=text_lines[0] if text_lines else "" + ) + else: + standard = "{h} {t}".format( + h=heading, t=text_lines[0] if text_lines else "" + ) + attr_list = self.format_attr_list(item, True) + result = attr_list + standard + else: + uid = item.uid + if settings.ENABLE_HEADERS: + if item.header: + uid = "{h} _{u}_".format(h=item.header, u=item.uid) + else: + uid = "{u}".format(u=item.uid) + + # Level and UID + if self.levels and settings.PUBLISH_BODY_LEVELS: + standard = "{h} {lev} {u}".format(h=heading, lev=level, u=uid) + else: + standard = "{h} {u}".format(h=heading, u=uid) + + attr_list = self.format_attr_list(item, True) + result = attr_list + standard + return result + + def _lines_asciidoc(self, obj, **kwargs): + """Yield lines for a AsciiDoc report. + + :param obj: Item, list of Items, or Document to publish + :param linkify: turn links into hyperlinks + + :return: iterator of lines of text + + """ + linkify = kwargs.get("linkify", False) + for item in iter_items(obj): + # Create item heading. + complete_heading = self._generate_heading_from_item(item) + yield complete_heading + + # Text + if item.text: + yield "" # break before text + yield from item.text.splitlines() + + # Reference + if item.ref: + yield "" # break before reference + yield self.format_ref(item) + + # Reference + if item.references: + yield "" # break before references + yield self.format_references(item) + + # Parent links + if item.links: + yield "" # break before links + items2 = item.parent_items + if settings.PUBLISH_CHILD_LINKS: + label = "Parent links:" + else: + label = "Links:" + links = self.format_links(items2, linkify) + label_links = self.format_label_links(label, links, linkify) + yield label_links + + # Child links + if settings.PUBLISH_CHILD_LINKS: + items2 = item.find_child_items() + if items2: + yield "" # break before links + label = "Child links:" + links = self.format_links(items2, linkify) + label_links = self.format_label_links(label, links, linkify) + yield label_links + + # Add custom publish attributes + if item.document and item.document.publish: + for attr in item.document.publish: + if not item.attribute(attr): + continue + yield "" # break before attribute name + yield "*{}*".format(attr) + yield "" # break before attribute content + yield "{}".format(item.attribute(attr)) + yield "" + + yield "" # break between items + + def copy_reference(self, path): + """Copy a referenced AsciiDoc file to the output, including directory structure.""" + src = Path.cwd().joinpath(path) + newpath = self.directory / path + os.makedirs(os.path.dirname(newpath), exist_ok=True) + shutil.copy(src, newpath) diff --git a/doorstop/core/publishers/base.py b/doorstop/core/publishers/base.py index e34d0f0bb..83a23ab2f 100644 --- a/doorstop/core/publishers/base.py +++ b/doorstop/core/publishers/base.py @@ -54,9 +54,14 @@ def __init__(self, obj, ext): } def setup(self, linkify, index, matrix): - """Check and store linkfy, index and matrix settings.""" + """Check and store linkify, index and matrix settings.""" if linkify is None: - self.linkify = is_tree(self.object) and self.ext in [".html", ".md", ".tex"] + self.linkify = is_tree(self.object) and self.ext in [ + ".html", + ".md", + ".tex", + ".adoc", + ] else: self.linkify = linkify if index is None: diff --git a/doorstop/core/publishers/markdown.py b/doorstop/core/publishers/markdown.py index 89f2c40c7..99fc8c8a3 100644 --- a/doorstop/core/publishers/markdown.py +++ b/doorstop/core/publishers/markdown.py @@ -22,6 +22,9 @@ def create_matrix(self, directory): def format_attr_list(self, item, linkify): """Create a Markdown attribute list for a heading.""" + if settings.PUBLISH_MKDOCS: + return "" + return " {{#{u}}}".format(u=item.uid) if linkify else "" def format_ref(self, item): @@ -136,7 +139,7 @@ def lines(self, obj, **kwargs): """ linkify = kwargs.get("linkify", False) toc = kwargs.get("toc", False) - if toc: + if toc and not settings.PUBLISH_MKDOCS: yield self.table_of_contents(linkify=linkify, obj=obj) yield from self._lines_markdown(obj, **kwargs) @@ -148,6 +151,10 @@ def _generate_heading_from_item(self, item, to_html=False): """ result = "" heading = "#" * item.depth + + if settings.PUBLISH_MKDOCS: + heading = "#" * (item.depth + 1) + level = format_level(item.level) if item.heading: text_lines = item.text.splitlines() diff --git a/doorstop/core/publishers/tests/test_publisher_html_doc.py b/doorstop/core/publishers/tests/test_publisher_html_doc.py index 3a947debc..5c4d91635 100644 --- a/doorstop/core/publishers/tests/test_publisher_html_doc.py +++ b/doorstop/core/publishers/tests/test_publisher_html_doc.py @@ -34,6 +34,7 @@ def setUp(self): traceability.csv traceability.html documents/ + EXT.html HLT.html LLT.html REQ.html diff --git a/doorstop/core/publishers/tests/test_publisher_latex_doc.py b/doorstop/core/publishers/tests/test_publisher_latex_doc.py index da84a1f96..77ae4011f 100644 --- a/doorstop/core/publishers/tests/test_publisher_latex_doc.py +++ b/doorstop/core/publishers/tests/test_publisher_latex_doc.py @@ -37,6 +37,7 @@ def setUp(self): self.dirpath = os.path.abspath(os.path.join("mock_%s" % __name__, self.hex)) os.makedirs(self.dirpath) self.expected_walk = """{n}/ + EXT.tex HLT.tex LLT.tex REQ.tex @@ -44,6 +45,7 @@ def setUp(self): TUT.tex Tutorial.tex compile.sh + doc-EXT.tex doc-HLT.tex doc-LLT.tex traceability.tex diff --git a/doorstop/core/publishers/tests/test_publisher_markdown_doc.py b/doorstop/core/publishers/tests/test_publisher_markdown_doc.py index 0c1af1b41..ab5b2576d 100644 --- a/doorstop/core/publishers/tests/test_publisher_markdown_doc.py +++ b/doorstop/core/publishers/tests/test_publisher_markdown_doc.py @@ -29,6 +29,7 @@ def setUp(self): self.dirpath = os.path.abspath(os.path.join("mock_%s" % __name__, self.hex)) os.makedirs(self.dirpath) self.expected_walk = """{n}/ + EXT.md HLT.md LLT.md REQ.md diff --git a/doorstop/core/tests/__init__.py b/doorstop/core/tests/__init__.py index be0a50f96..aca01c4b3 100644 --- a/doorstop/core/tests/__init__.py +++ b/doorstop/core/tests/__init__.py @@ -4,7 +4,7 @@ import logging import os -from typing import List +from typing import Any, Dict, List from unittest.mock import MagicMock, Mock, patch from doorstop.core.base import BaseFileObject @@ -95,6 +95,7 @@ def __init__(self): self.itemformat = "yaml" self._items: List[Item] = [] self.extended_reviewed: List[str] = [] + self.extensions: Dict[str, Any] = {} def __iter__(self): yield from self._items @@ -103,6 +104,15 @@ def set_items(self, items): self._items = items +class MockSimpleDocumentExtensions(MockSimpleDocument): + """Mock Document class that enable extensions.""" + + def __init__(self, **kwargs): + super().__init__() + for k, v in kwargs.items(): + self.extensions[k] = v + + class MockDocumentSkip(MockDocument): # pylint: disable=W0223,R0902 """Mock Document class that is always skipped in tree placement.""" diff --git a/doorstop/core/tests/files/published.html b/doorstop/core/tests/files/published.html index 3fdbe718f..081b52931 100644 --- a/doorstop/core/tests/files/published.html +++ b/doorstop/core/tests/files/published.html @@ -105,7 +105,22 @@

1.6 REQ004

Hello, world!

2.1 Plantuml REQ002

Hello, world!

-

AuthorCreate DocumentCreate ItemLink Item to DocumentLink Item to other ItemEdit ItemReview ItemDelete ItemDelete DocumentExportImportReviewerSystemSuspect ChangesIntegrity

+

plantuml format="svg_inline" alt="Use Cases of Doorstop" title="Use Cases of Doorstop" +@startuml +Author --> (Create Document) +Author --> (Create Item) +Author --> (Link Item to Document) +Author --> (Link Item to other Item) +Author --> (Edit Item) +Author --> (Review Item) +Author -> (Delete Item) +Author -> (Delete Document) +(Export) <- (Author) +(Import) <- (Author) +Reviewer --> (Review Item) +System --> (Suspect Changes) +System --> (Integrity) +@enduml

Child links: TST001, TST002

2.1 REQ2-001

Hello, world!

diff --git a/doorstop/core/tests/files/published2.html b/doorstop/core/tests/files/published2.html index ecc2a319f..f1c1435d5 100644 --- a/doorstop/core/tests/files/published2.html +++ b/doorstop/core/tests/files/published2.html @@ -105,7 +105,22 @@

1.6 REQ004

Hello, world!

2.1 Plantuml REQ002

Hello, world!

-

AuthorCreate DocumentCreate ItemLink Item to DocumentLink Item to other ItemEdit ItemReview ItemDelete ItemDelete DocumentExportImportReviewerSystemSuspect ChangesIntegrity

+

plantuml format="svg_inline" alt="Use Cases of Doorstop" title="Use Cases of Doorstop" +@startuml +Author --> (Create Document) +Author --> (Create Item) +Author --> (Link Item to Document) +Author --> (Link Item to other Item) +Author --> (Edit Item) +Author --> (Review Item) +Author -> (Delete Item) +Author -> (Delete Document) +(Export) <- (Author) +(Import) <- (Author) +Reviewer --> (Review Item) +System --> (Suspect Changes) +System --> (Integrity) +@enduml

2.1 REQ2-001

Hello, world!

Test Math Expressions in Latex Style:

diff --git a/doorstop/core/tests/test_all.py b/doorstop/core/tests/test_all.py index 155c325aa..7c8c975db 100644 --- a/doorstop/core/tests/test_all.py +++ b/doorstop/core/tests/test_all.py @@ -11,6 +11,7 @@ import shutil import tempfile import unittest +from typing import List from unittest.mock import Mock, patch import openpyxl @@ -388,6 +389,8 @@ def setUp(self): def tearDown(self): os.chdir(self.cwd) + # until we only support 3.12+ ignore this, as we need to move to onexc instead of onerror + # pylint: disable=W4903 shutil.rmtree(self.temp, onerror=on_error_with_retry) def test_import_yml(self): @@ -522,6 +525,8 @@ def setUp(self): self.temp = tempfile.mkdtemp() def tearDown(self): + # until we only support 3.12+ ignore this, as we need to move to onexc instead of onerror + # pylint: disable=W4903 shutil.rmtree(self.temp, onerror=on_error_with_retry) def test_export_yml(self): @@ -578,6 +583,8 @@ def setUp(self): def tearDown(self): if os.path.exists(self.temp): + # until we only support 3.12+ ignore this, as we need to move to onexc instead of onerror + # pylint: disable=W4903 shutil.rmtree(self.temp, onerror=on_error_with_retry) def test_publish_html(self): @@ -649,8 +656,17 @@ def test_lines_markdown_document_without_child_links(self): self.assertEqual(expected, text) common.write_text(text, path) - def test_lines_html_document_linkify(self): + @patch("plantuml_markdown.PlantUMLPreprocessor.run") + @patch("plantuml_markdown.PlantUMLPreprocessor.__init__") + def test_lines_html_document_linkify(self, ext_init, ext_run): """Verify HTML can be published from a document.""" + + def run(lines: List[str]) -> List[str]: + return lines + + ext_init.return_value = None + ext_run.side_effect = run + path = os.path.join(FILES, "published.html") expected = common.read_text(path) # Act @@ -664,9 +680,18 @@ def test_lines_html_document_linkify(self): common.write_text(actual, path) self.assertEqual(expected, actual) + @patch("plantuml_markdown.PlantUMLPreprocessor.run") + @patch("plantuml_markdown.PlantUMLPreprocessor.__init__") @patch("doorstop.settings.PUBLISH_CHILD_LINKS", False) - def test_lines_html_document_without_child_links(self): + def test_lines_html_document_without_child_links(self, ext_init, ext_run): """Verify HTML can be published from a document w/o child links.""" + + def run(lines: List[str]) -> List[str]: + return lines + + ext_init.return_value = None + ext_run.side_effect = run + path = os.path.join(FILES, "published2.html") expected = common.read_text(path) # Act diff --git a/doorstop/core/tests/test_common.py b/doorstop/core/tests/test_common.py index a7c3d0b30..42ca32fb2 100644 --- a/doorstop/core/tests/test_common.py +++ b/doorstop/core/tests/test_common.py @@ -152,5 +152,5 @@ def test_dump_markdown(self): # header -text text text""".lstrip(), +text text text\n""".lstrip(), ) diff --git a/doorstop/core/tests/test_item.py b/doorstop/core/tests/test_item.py index 8f6088ca8..cc7ad31f4 100644 --- a/doorstop/core/tests/test_item.py +++ b/doorstop/core/tests/test_item.py @@ -7,6 +7,7 @@ import unittest from unittest.mock import MagicMock, Mock, patch +import doorstop.core.editor from doorstop import common, settings from doorstop.common import DoorstopError from doorstop.core.item import Item, UnknownItem @@ -471,6 +472,41 @@ def test_edit(self, mock_launch, mock_load): mock_launch.assert_called_once_with(self.item.path, tool="mock_editor") mock_load.assert_called_once_with(True) + @patch("doorstop.core.editor.os.name", "nt") + @patch("doorstop.core.editor.sys.platform", "nt") + @patch("doorstop.core.editor.shutil.which") + @patch("doorstop.core.editor._call") + def test_launch_os_nt_cygwin(self, mock_call, mock_which): + mock_call.side_effect = FileNotFoundError + mock_which.return_value = "cygstart" + self.assertRaises(DoorstopError, doorstop.core.editor.launch, "") + mock_call.assert_called_once_with(["cygstart", ""]) + + @patch("doorstop.core.editor.os.name", "nt") + @patch("doorstop.core.editor.sys.platform", "nt") + @patch("doorstop.core.editor.shutil.which") + @patch("doorstop.core.editor._call") + def test_launch_os_nt(self, mock_call, mock_which): + mock_call.side_effect = FileNotFoundError + mock_which.return_value = "start" + self.assertRaises(DoorstopError, doorstop.core.editor.launch, "") + mock_call.assert_called_once_with(["start", ""]) + + @patch("doorstop.core.editor.sys.platform", "darwin") + @patch("doorstop.core.editor._call") + def test_launch_os_darwin(self, mock_call): + mock_call.side_effect = FileNotFoundError + self.assertRaises(DoorstopError, doorstop.core.editor.launch, "") + mock_call.assert_called_once_with(["open", ""]) + + @patch("doorstop.core.editor.os.name", "posix") + @patch("doorstop.core.editor.sys.platform", "posix") + @patch("doorstop.core.editor._call") + def test_launch_os_posix(self, mock_call): + mock_call.side_effect = FileNotFoundError + self.assertRaises(DoorstopError, doorstop.core.editor.launch, "") + mock_call.assert_called_once_with(["xdg-open", ""]) + def test_link(self): """Verify links can be added to an item.""" self.item.link("abc") diff --git a/doorstop/core/tests/test_item_extensions.py b/doorstop/core/tests/test_item_extensions.py new file mode 100644 index 000000000..76bdf9687 --- /dev/null +++ b/doorstop/core/tests/test_item_extensions.py @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: LGPL-3.0-only +# pylint: disable=C0302 + +"""Unit tests for the doorstop.core.item with extensions enabled.""" + +import os +import unittest +from types import ModuleType +from unittest.mock import patch + +from doorstop.common import import_path_as_module +from doorstop.core.tests import TESTS_ROOT, MockItem, MockSimpleDocumentExtensions + + +class TestItem(unittest.TestCase): + """Unit tests for the Item class.""" + + # pylint: disable=protected-access,no-value-for-parameter + + def setUp(self): + path = os.path.join("path", "to", "RQ001.yml") + self.item = MockItem(MockSimpleDocumentExtensions(), path) + + @patch("doorstop.settings.CACHE_PATHS", False) + def test_load_custom_validator_per_folder(self): + """Load a valid custom validator per folder.""" + path = os.path.join("path", "to", "RQ001.yml") + self.item = MockItem( + MockSimpleDocumentExtensions( + item_validator=f"{TESTS_ROOT}/validators/validator_dummy.py" + ), + path, + ) + document = self.item.document + validator = import_path_as_module(document.extensions["item_validator"]) + + self.assertEqual(isinstance(validator, ModuleType), True) + + @patch("doorstop.settings.CACHE_PATHS", False) + def test_load_custom_validator_per_folder_and_fails(self): + """Load a invalid custom validator per folder and fails with FileNotFoundError.""" + path = os.path.join("path", "to", "RQ001.yml") + self.item = MockItem( + MockSimpleDocumentExtensions( + item_validator=f"{TESTS_ROOT}/files/validator_dummy2.py" + ), + path, + ) + document = self.item.document + try: + validator = import_path_as_module(document.extensions["item_validator"]) + except FileNotFoundError: + validator = FileNotFoundError + + self.assertEqual(FileNotFoundError, validator) + + @patch("doorstop.settings.CACHE_PATHS", False) + def test_find_references_and_get_sha(self): + """Verify an item's references can be found.""" + path = os.path.join("path", "to", "RQ001.yml") + self.item = MockItem(MockSimpleDocumentExtensions(item_sha_required=True), path) + self.item.root = TESTS_ROOT + + self.item.references = [ + {"path": "files/REQ001.yml", "type": "file"}, + {"path": "files/REQ002.yml", "type": "file"}, + ] + # Generate sha through review + self.item.review() + refs = self.item.references + + self.assertIn("sha", refs[0]) + self.assertIn("sha", refs[1]) + + @patch("doorstop.settings.CACHE_PATHS", False) + def test_no_sha_ref(self): + """Verify sha is not obtained if extension is not enabled.""" + path = os.path.join("path", "to", "RQ001.yml") + self.item = MockItem( + MockSimpleDocumentExtensions(), + path, + ) + + self.item.root = TESTS_ROOT + + self.item.references = [ + {"path": "files/REQ001.yml", "type": "file"}, + {"path": "files/REQ002.yml", "type": "file"}, + ] + # without item_sha_required, sha must return None + self.item.review() + refs = self.item.references + sha = self.item._hash_reference(refs[0]["path"]) + self.assertNotIn("sha", refs[0].keys()) + self.assertIsNone(sha) diff --git a/doorstop/core/tests/test_publisher.py b/doorstop/core/tests/test_publisher.py index 064993d75..cc4efbdce 100644 --- a/doorstop/core/tests/test_publisher.py +++ b/doorstop/core/tests/test_publisher.py @@ -41,6 +41,8 @@ def setUp(self): def tearDownClass(cls): """Remove test folder.""" if os.path.exists("mock_%s" % __name__): + # until we only support 3.12+ ignore this, as we need to move to onexc instead of onerror + # pylint: disable=W4903 rmtree("mock_%s" % __name__, onerror=on_error_with_retry) def test_publish_document_unknown(self): diff --git a/doorstop/core/tests/test_template.py b/doorstop/core/tests/test_template.py index 46e335292..12d95f3d1 100644 --- a/doorstop/core/tests/test_template.py +++ b/doorstop/core/tests/test_template.py @@ -43,6 +43,8 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): """Remove test folder.""" + # until we only support 3.12+ ignore this, as we need to move to onexc instead of onerror + # pylint: disable=W4903 rmtree(cls.testdir, onerror=on_error_with_retry) def test_standard_html_doc(self): diff --git a/doorstop/core/tests/validators/validator_dummy.py b/doorstop/core/tests/validators/validator_dummy.py new file mode 100644 index 000000000..5aeb389ce --- /dev/null +++ b/doorstop/core/tests/validators/validator_dummy.py @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: LGPL-3.0-only + +from doorstop import DoorstopError, DoorstopInfo, DoorstopWarning + + +def item_validator(item): + if item: + yield DoorstopInfo("Loaded") diff --git a/doorstop/core/vcs/__init__.py b/doorstop/core/vcs/__init__.py index d0c6f13d1..ea533028a 100644 --- a/doorstop/core/vcs/__init__.py +++ b/doorstop/core/vcs/__init__.py @@ -2,18 +2,17 @@ """Interfaces to version control systems.""" -import logging import os +from pathlib import Path from doorstop import common from doorstop.common import DoorstopError -from doorstop.core.vcs import git, mercurial, mockvcs, subversion, veracity +from doorstop.core.vcs import git, mercurial, mockvcs, subversion DEFAULT = mockvcs.WorkingCopy DIRECTORIES = { git.WorkingCopy.DIRECTORY: git.WorkingCopy, subversion.WorkingCopy.DIRECTORY: subversion.WorkingCopy, - veracity.WorkingCopy.DIRECTORY: veracity.WorkingCopy, mercurial.WorkingCopy.DIRECTORY: mercurial.WorkingCopy, DEFAULT.DIRECTORY: DEFAULT, } @@ -48,9 +47,15 @@ def find_root(cwd): def load(path): """Return a working copy for the specified path.""" + if ".doorstop-external" in path: + realpath = Path(path.split(".doorstop-external")[0]) # Cheat to get the root. + # We only support this with git... + return DIRECTORIES[".git"](realpath) # type: ignore + for directory in os.listdir(path): if directory in DIRECTORIES: return DIRECTORIES[directory](path) # type: ignore - log.warning("no working copy found at: {}".format(path)) + if ".doorstop-external" not in path: + log.warning("no working copy found at: {}".format(path)) return DEFAULT(path) diff --git a/doorstop/core/vcs/base.py b/doorstop/core/vcs/base.py index ed553bfdc..34cf2085b 100644 --- a/doorstop/core/vcs/base.py +++ b/doorstop/core/vcs/base.py @@ -22,6 +22,7 @@ class BaseWorkingCopy(metaclass=ABCMeta): def __init__(self, path): self.path = path self._ignores_cache: Optional[List[str]] = None + self._unhidden_cache: Optional[List[str]] = None self._path_cache: Optional[List[Tuple[str, str, str]]] = None @staticmethod @@ -78,9 +79,24 @@ def ignores(self): for line in common.read_lines(path): pattern = line.strip(" @\\/*\n") if pattern and not pattern.startswith("#"): - self._ignores_cache.append("*" + pattern + "*") + self._ignores_cache.append(pattern + "*") yield from self._ignores_cache + @property + def unhidden(self): + """Yield glob expressions for paths that should not be hidden.""" + if self._unhidden_cache is None: + self._unhidden_cache = [] + log.debug("reading and caching the unhidden patterns...") + path = os.path.join(self.path, settings.UNHIDDEN_FILEPATH) + if os.path.isfile(path): + for line in common.read_lines(path): + log.debug(f"unhiding {line}") + pattern = line.strip(" @\\/*\n") + if pattern and not pattern.startswith("#"): + self._unhidden_cache.append("*" + pattern + "*") + yield from self._unhidden_cache + @property def paths(self): """Yield non-ignored paths in the working copy.""" @@ -94,8 +110,16 @@ def paths(self): # Skip ignored paths if self.ignored(relpath): continue - # Skip hidden paths - if os.path.sep + "." in os.path.sep + relpath: + # Don't skip unhidden paths + if self.is_unhidden(relpath): + log.debug(f"not skipping: {relpath}") + self._path_cache.append((path, filename, relpath)) + continue + # Skip hidden paths except for 'external folder' + if ( + ".doorstop-external" not in relpath + and os.path.sep + "." in os.path.sep + relpath + ): continue self._path_cache.append((path, filename, relpath)) yield from self._path_cache @@ -106,3 +130,10 @@ def ignored(self, path): if fnmatch.fnmatch(path, pattern): return True return False + + def is_unhidden(self, path): + """Determine if a path matches a pattern that should not hidden.""" + for pattern in self.unhidden: + if fnmatch.fnmatch(path, pattern): + return True + return False diff --git a/doorstop/core/vcs/tests/test_all.py b/doorstop/core/vcs/tests/test_all.py index 16a05e381..450f4d915 100644 --- a/doorstop/core/vcs/tests/test_all.py +++ b/doorstop/core/vcs/tests/test_all.py @@ -20,5 +20,5 @@ def test_ignores(self): patterns = list(self.wc.ignores) for pattern in patterns: print(pattern) - self.assertIn("*__pycache__*", patterns) - self.assertIn("*build*", patterns) + self.assertIn("__pycache__*", patterns) + self.assertIn("build*", patterns) diff --git a/doorstop/core/vcs/tests/test_commands.py b/doorstop/core/vcs/tests/test_commands.py index 531d6925e..5b4806725 100644 --- a/doorstop/core/vcs/tests/test_commands.py +++ b/doorstop/core/vcs/tests/test_commands.py @@ -124,45 +124,6 @@ def test_commit(self, mock_call): mock_call.assert_has_calls(calls) -@patch("subprocess.call") -class TestVeracity(BaseTestCase, unittest.TestCase): - """Tests for the Veracity plugin.""" - - DIRECTORY = ".sgdrawer" - - def test_lock(self, mock_call): - """Verify Veracity can lock files.""" - self.lock() - calls = [call(("vv", "pull")), call(("vv", "update"))] - mock_call.assert_has_calls(calls) - - def test_edit(self, mock_call): - """Verify Veracity can (fake) edit files.""" - self.edit() - mock_call.assert_has_calls([]) - - def test_add(self, mock_call): - """Verify Veracity can add files.""" - self.add() - calls = [call(("vv", "add", self.path))] - mock_call.assert_has_calls(calls) - - def test_delete(self, mock_call): - """Verify Veracity can delete files.""" - self.delete() - calls = [call(("vv", "remove", self.path))] - mock_call.assert_has_calls(calls) - - def test_commit(self, mock_call): - """Verify Veracity can commit files.""" - self.commit() - calls = [ - call(("vv", "commit", "--message", self.message)), - call(("vv", "push")), - ] - mock_call.assert_has_calls(calls) - - @patch("subprocess.call") class TestMercurial(BaseTestCase, unittest.TestCase): """Tests for the Mercurial plugin.""" diff --git a/doorstop/core/vcs/veracity.py b/doorstop/core/vcs/veracity.py deleted file mode 100644 index 65518a3e0..000000000 --- a/doorstop/core/vcs/veracity.py +++ /dev/null @@ -1,34 +0,0 @@ -# SPDX-License-Identifier: LGPL-3.0-only - -"""Plug-in module to store requirements in a Veracity repository.""" - -from doorstop import common -from doorstop.core.vcs.base import BaseWorkingCopy - -log = common.logger(__name__) - - -class WorkingCopy(BaseWorkingCopy): - """Veracity working copy.""" - - DIRECTORY = ".sgdrawer" - IGNORES = (".sgignores", ".vvignores") - - def lock(self, path): - log.debug("`vv` does not support scripted locking: %s", path) - self.call("vv", "pull") - self.call("vv", "update") - - def edit(self, path): - log.info("`vv` adds all changes") - - def add(self, path): - self.call("vv", "add", path) - - def delete(self, path): - self.call("vv", "remove", path) - - def commit(self, message=None): - message = message or input("Commit message: ") - self.call("vv", "commit", "--message", message) - self.call("vv", "push") diff --git a/doorstop/settings.py b/doorstop/settings.py index 264ef02cb..b568e5777 100644 --- a/doorstop/settings.py +++ b/doorstop/settings.py @@ -49,6 +49,7 @@ PUBLISH_CHILD_LINKS = True # include child links when publishing PUBLISH_BODY_LEVELS = True # include levels on non-header items PUBLISH_HEADING_LEVELS = True # include levels on header items +PUBLISH_MKDOCS = False # generate markdown for rendering by mkdocs ENABLE_HEADERS = True # use headers if defined WRITE_LINESEPERATOR = os.linesep @@ -63,3 +64,6 @@ # Server settings SERVER_HOST = None # '' = server not specified, None = no server in use SERVER_PORT = 7867 + +# Unhidden file +UNHIDDEN_FILEPATH = ".doorstop_unhidden" # list of paths that should not be hidden diff --git a/poetry.lock b/poetry.lock index 4154f612d..e9d009cba 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "altgraph" @@ -13,51 +13,17 @@ files = [ [[package]] name = "astroid" -version = "2.13.5" +version = "3.2.4" description = "An abstract syntax tree for Python with inference support." optional = false -python-versions = ">=3.7.2" +python-versions = ">=3.8.0" files = [ - {file = "astroid-2.13.5-py3-none-any.whl", hash = "sha256:6891f444625b6edb2ac798829b689e95297e100ddf89dbed5a8c610e34901501"}, - {file = "astroid-2.13.5.tar.gz", hash = "sha256:df164d5ac811b9f44105a72b8f9d5edfb7b5b2d7e979b04ea377a77b3229114a"}, + {file = "astroid-3.2.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, + {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, ] [package.dependencies] -lazy-object-proxy = ">=1.4.0" typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} -wrapt = [ - {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, - {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, -] - -[[package]] -name = "atomicwrites" -version = "1.4.1" -description = "Atomic file writes." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, -] - -[[package]] -name = "attrs" -version = "23.2.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] [[package]] name = "beautifulsoup4" @@ -82,33 +48,33 @@ lxml = ["lxml"] [[package]] name = "black" -version = "23.12.1" +version = "24.8.0" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, - {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, - {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, - {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, - {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, - {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, - {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, - {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, - {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, - {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, - {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, - {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, - {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, - {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, - {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, - {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, - {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, - {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, - {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, - {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, - {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, - {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, + {file = "black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6"}, + {file = "black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb"}, + {file = "black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42"}, + {file = "black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a"}, + {file = "black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1"}, + {file = "black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af"}, + {file = "black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4"}, + {file = "black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af"}, + {file = "black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368"}, + {file = "black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed"}, + {file = "black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018"}, + {file = "black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2"}, + {file = "black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd"}, + {file = "black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2"}, + {file = "black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e"}, + {file = "black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920"}, + {file = "black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c"}, + {file = "black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e"}, + {file = "black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47"}, + {file = "black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb"}, + {file = "black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed"}, + {file = "black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f"}, ] [package.dependencies] @@ -139,13 +105,13 @@ files = [ [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] [[package]] @@ -285,63 +251,83 @@ files = [ [[package]] name = "coverage" -version = "7.4.3" +version = "7.6.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8580b827d4746d47294c0e0b92854c85a92c2227927433998f0d3320ae8a71b6"}, - {file = "coverage-7.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718187eeb9849fc6cc23e0d9b092bc2348821c5e1a901c9f8975df0bc785bfd4"}, - {file = "coverage-7.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:767b35c3a246bcb55b8044fd3a43b8cd553dd1f9f2c1eeb87a302b1f8daa0524"}, - {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7f19afe0cce50039e2c782bff379c7e347cba335429678450b8fe81c4ef96d"}, - {file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba3a8aaed13770e970b3df46980cb068d1c24af1a1968b7818b69af8c4347efb"}, - {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ee866acc0861caebb4f2ab79f0b94dbfbdbfadc19f82e6e9c93930f74e11d7a0"}, - {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:506edb1dd49e13a2d4cac6a5173317b82a23c9d6e8df63efb4f0380de0fbccbc"}, - {file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd6545d97c98a192c5ac995d21c894b581f1fd14cf389be90724d21808b657e2"}, - {file = "coverage-7.4.3-cp310-cp310-win32.whl", hash = "sha256:f6a09b360d67e589236a44f0c39218a8efba2593b6abdccc300a8862cffc2f94"}, - {file = "coverage-7.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:18d90523ce7553dd0b7e23cbb28865db23cddfd683a38fb224115f7826de78d0"}, - {file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"}, - {file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"}, - {file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"}, - {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"}, - {file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"}, - {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"}, - {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"}, - {file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"}, - {file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"}, - {file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"}, - {file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"}, - {file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"}, - {file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"}, - {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"}, - {file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"}, - {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"}, - {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"}, - {file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"}, - {file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"}, - {file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"}, - {file = "coverage-7.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28ca2098939eabab044ad68850aac8f8db6bf0b29bc7f2887d05889b17346454"}, - {file = "coverage-7.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:280459f0a03cecbe8800786cdc23067a8fc64c0bd51dc614008d9c36e1659d7e"}, - {file = "coverage-7.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c0cdedd3500e0511eac1517bf560149764b7d8e65cb800d8bf1c63ebf39edd2"}, - {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9babb9466fe1da12417a4aed923e90124a534736de6201794a3aea9d98484e"}, - {file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dec9de46a33cf2dd87a5254af095a409ea3bf952d85ad339751e7de6d962cde6"}, - {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:16bae383a9cc5abab9bb05c10a3e5a52e0a788325dc9ba8499e821885928968c"}, - {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2c854ce44e1ee31bda4e318af1dbcfc929026d12c5ed030095ad98197eeeaed0"}, - {file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ce8c50520f57ec57aa21a63ea4f325c7b657386b3f02ccaedeccf9ebe27686e1"}, - {file = "coverage-7.4.3-cp38-cp38-win32.whl", hash = "sha256:708a3369dcf055c00ddeeaa2b20f0dd1ce664eeabde6623e516c5228b753654f"}, - {file = "coverage-7.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:1bf25fbca0c8d121a3e92a2a0555c7e5bc981aee5c3fdaf4bb7809f410f696b9"}, - {file = "coverage-7.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b253094dbe1b431d3a4ac2f053b6d7ede2664ac559705a704f621742e034f1f"}, - {file = "coverage-7.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77fbfc5720cceac9c200054b9fab50cb2a7d79660609200ab83f5db96162d20c"}, - {file = "coverage-7.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6679060424faa9c11808598504c3ab472de4531c571ab2befa32f4971835788e"}, - {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af154d617c875b52651dd8dd17a31270c495082f3d55f6128e7629658d63765"}, - {file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8640f1fde5e1b8e3439fe482cdc2b0bb6c329f4bb161927c28d2e8879c6029ee"}, - {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:69b9f6f66c0af29642e73a520b6fed25ff9fd69a25975ebe6acb297234eda501"}, - {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0842571634f39016a6c03e9d4aba502be652a6e4455fadb73cd3a3a49173e38f"}, - {file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a78ed23b08e8ab524551f52953a8a05d61c3a760781762aac49f8de6eede8c45"}, - {file = "coverage-7.4.3-cp39-cp39-win32.whl", hash = "sha256:c0524de3ff096e15fcbfe8f056fdb4ea0bf497d584454f344d59fce069d3e6e9"}, - {file = "coverage-7.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0209a6369ccce576b43bb227dc8322d8ef9e323d089c6f3f26a597b09cb4d2aa"}, - {file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"}, - {file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"}, + {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, + {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, + {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, + {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, + {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, + {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, + {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, + {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, + {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, + {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, + {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, + {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, + {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, + {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, + {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, + {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, + {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, + {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, ] [package.dependencies] @@ -413,6 +399,72 @@ files = [ {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, ] +[[package]] +name = "dulwich" +version = "0.22.1" +description = "Python Git Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "dulwich-0.22.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:892914dc2e80403d16e59a3b440044f6092fde5ffd4ec1fdf36d6ff20a8e624d"}, + {file = "dulwich-0.22.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b03092399f0f5d3e112405b890128afdb9e1f203eafb812f5d9105b0f5fac9d4"}, + {file = "dulwich-0.22.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a2c790517ed884bc1b1590806222ab44989eeb7e7f14dfa915561c7ee3b9ac73"}, + {file = "dulwich-0.22.1-cp310-cp310-win32.whl", hash = "sha256:524d3497a86f79959c9c1d729715d60d8171ed3f71621d45afb4faee5a47e8a1"}, + {file = "dulwich-0.22.1-cp310-cp310-win_amd64.whl", hash = "sha256:d3146843b972f744aed551e8ac9fac5714baa864393e480586d467b7b4488426"}, + {file = "dulwich-0.22.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:82f26e592e9a36ab33bcdb419c7d53320e26c85dfc254cdb84f5f561a2fcaabf"}, + {file = "dulwich-0.22.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e90b8a2f24149c5803b733a24f1a016a2943b1f5a9ab2360db545e4638354c35"}, + {file = "dulwich-0.22.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b069639757b2f287f9cd0daf6765b536558c5e28263bbbb28e3d1925bce75400"}, + {file = "dulwich-0.22.1-cp311-cp311-win32.whl", hash = "sha256:3ae006498fea11515027a417e6e68b82e1c195d3516188ba2cc08210e3022d14"}, + {file = "dulwich-0.22.1-cp311-cp311-win_amd64.whl", hash = "sha256:a18d1392eabd02f337dcba23d723a4dcca87274ce8693cf88e6320f38bc3fdcd"}, + {file = "dulwich-0.22.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:12482e318895da9acabea7c0cc70b35d36833e7cb2def511ab3a63617f5c1af3"}, + {file = "dulwich-0.22.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dc42afedc8cda4f2fd15a06d2e9e41281074a02cdf31bb2e0dde4d80766a408"}, + {file = "dulwich-0.22.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e3c7774232a2c9b195bde4fb72ad71455e877a9e4e9c0b17a57b1d9bd478838c"}, + {file = "dulwich-0.22.1-cp312-cp312-win32.whl", hash = "sha256:41dfc52db29a06fe23a5029abc3bc13503e28233b1c3a9614bc1e5c4d6adc1ce"}, + {file = "dulwich-0.22.1-cp312-cp312-win_amd64.whl", hash = "sha256:9d19f04ecd4628a0e4587b4c4e98e040b87924c1362ae5aa27420435f05d5dd8"}, + {file = "dulwich-0.22.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0d72a88c7af8fafa14c8743e8923c8d46bd0b850a0b7f5e34eb49201f1ead88e"}, + {file = "dulwich-0.22.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e36c8a3bb09db5730b3d5014d087bce977e878825cdd7ba8285abcd81c43bc0"}, + {file = "dulwich-0.22.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd51e77ff1b4ca08bc9b09b85646a3e77f275827b7b30180d76d769ce608e64d"}, + {file = "dulwich-0.22.1-cp37-cp37m-win32.whl", hash = "sha256:739ef91aeb13fa2aa187d0efd46d0ac168301f54a6ef748565c42876b4b3ce71"}, + {file = "dulwich-0.22.1-cp37-cp37m-win_amd64.whl", hash = "sha256:91966b7b48ec939e5083b03c9154fc450508056f01650ecb58724095307427f5"}, + {file = "dulwich-0.22.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:86be1e283d78cc3f7daee1dcd0254122160cde71ca8c5348315156045f8ac2bb"}, + {file = "dulwich-0.22.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926d671654a2f8cfa0b2fcb6b0c46833af95b5265d27a5c56c49c5a10f3ff3ba"}, + {file = "dulwich-0.22.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:467ff87fc4c61a23424b32acd952476ba17e7f7eeb8090e5957f68129784a35f"}, + {file = "dulwich-0.22.1-cp38-cp38-win32.whl", hash = "sha256:f9e10678fe0692c5167553981d97cbe342ed055c49016aef10da336e2962b1f2"}, + {file = "dulwich-0.22.1-cp38-cp38-win_amd64.whl", hash = "sha256:6386165c64ba5f61c416301f7f32bb899f8200ca575d76888697a42fda8a92d2"}, + {file = "dulwich-0.22.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:84db8aef08df6431b017cc3abe57b3d6885fd7436eec8d715603c309353b233c"}, + {file = "dulwich-0.22.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:155124219e6ce4b116d30ed1b9cc63c88021966b29ce761d3ce3caba064f9a13"}, + {file = "dulwich-0.22.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7579429e89deac6659b4ea70eb3de9063bb40508fd4a8a020fa67b02e0b59f4f"}, + {file = "dulwich-0.22.1-cp39-cp39-win32.whl", hash = "sha256:454d073e628043dde4f9bd34517736c1889dbe6417099bbae2119873b8d4d5da"}, + {file = "dulwich-0.22.1-cp39-cp39-win_amd64.whl", hash = "sha256:e1b51d26108a832f151da8856a93676cc1a5cd8dd0bc20f06f4aee5774a7f0f9"}, + {file = "dulwich-0.22.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4c509e8172b9438536946097768413f297229b03eff064e4e06749cf5c28df78"}, + {file = "dulwich-0.22.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64eebe1d709539d6e80440fa1185f1eeb260d53bcb6435b1f753b4ce90a65e82"}, + {file = "dulwich-0.22.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52a8ddd1d9b5681de216a7af718720f5202d3c093ecc10dd4dfac6d25da605a6"}, + {file = "dulwich-0.22.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7244b796dd7e191753b822ac0ca871a4b9139b0b850770ac5bd347d5f8c76768"}, + {file = "dulwich-0.22.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e7798e842ec506d25f21e825259b70109325ac1c9b43c2e287aad7559455951b"}, + {file = "dulwich-0.22.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac9fcf7c5cf1e9d0bcc643672f81bf43ec81f6495b99809649f5bfcdff633ab0"}, + {file = "dulwich-0.22.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e346c1b86c5e5f175ca8f87f3873eea8b2e0eeb5d52033b475cf85641cb200c2"}, + {file = "dulwich-0.22.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:b2054e1f2c7041857ce129443bde23298ca37592ce82f0fb5ed5704d5f3708dd"}, + {file = "dulwich-0.22.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3ad3462d070b678fe61d3bdd7c6ac3fdbd25cca66f32b6edf589dd88fff251d2"}, + {file = "dulwich-0.22.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc6575476539c0b4924abab3896fc76be2f413d5baa6b083c4dfc4abc59329e"}, + {file = "dulwich-0.22.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3de7a2eba26ff13a79670f78f73fc86fb8c87100508119f3b6bd61451bfdd4bf"}, + {file = "dulwich-0.22.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b2c3186cf76d598a9d42b35e09ef35d499118b4197624ba5bba1b3a39ac6a75f"}, + {file = "dulwich-0.22.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a366cdba24b8df31ad70b82bae55baa696c453678c1346da8390396a1d5cce4"}, + {file = "dulwich-0.22.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fb61891b2675664dc89d486eb5199e3659179ae04fc0a863ffc7e16b782b624"}, + {file = "dulwich-0.22.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ea4c5feedd35e8bde175a9ab91ef6705c3cef5ee209eeb2f67dd0b59ff1825f"}, + {file = "dulwich-0.22.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:20f61f6dc0b075ca6459acbfb9527ee0e1ee02dccbed126dc492600bb7310d86"}, + {file = "dulwich-0.22.1.tar.gz", hash = "sha256:e36d85967cfbf25da1c7bc3d6921adc5baa976969d926aaf1582bd5fd7e94758"}, +] + +[package.dependencies] +setuptools = {version = "*", markers = "python_version >= \"3.12\""} +urllib3 = ">=1.25" + +[package.extras] +fastimport = ["fastimport"] +https = ["urllib3 (>=1.24.1)"] +paramiko = ["paramiko"] +pgp = ["gpg"] + [[package]] name = "et-xmlfile" version = "1.1.0" @@ -424,6 +476,20 @@ files = [ {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"}, ] +[[package]] +name = "exceptiongroup" +version = "1.2.2" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, +] + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "ghp-import" version = "2.1.0" @@ -443,34 +509,15 @@ dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "idna" -version = "3.6" +version = "3.8" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, -] - -[[package]] -name = "importlib-metadata" -version = "7.0.1" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.8" +python-versions = ">=3.6" files = [ - {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, - {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, + {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, + {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, ] -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] - [[package]] name = "iniconfig" version = "2.0.0" @@ -498,13 +545,13 @@ colors = ["colorama (>=0.4.6)"] [[package]] name = "jinja2" -version = "3.1.3" +version = "3.1.4" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, - {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] [package.dependencies] @@ -513,52 +560,6 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] -[[package]] -name = "lazy-object-proxy" -version = "1.10.0" -description = "A fast and thorough lazy object proxy." -optional = false -python-versions = ">=3.8" -files = [ - {file = "lazy-object-proxy-1.10.0.tar.gz", hash = "sha256:78247b6d45f43a52ef35c25b5581459e85117225408a4128a3daf8bf9648ac69"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:855e068b0358ab916454464a884779c7ffa312b8925c6f7401e952dcf3b89977"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab7004cf2e59f7c2e4345604a3e6ea0d92ac44e1c2375527d56492014e690c3"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc0d2fc424e54c70c4bc06787e4072c4f3b1aa2f897dfdc34ce1013cf3ceef05"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e2adb09778797da09d2b5ebdbceebf7dd32e2c96f79da9052b2e87b6ea495895"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1f711e2c6dcd4edd372cf5dec5c5a30d23bba06ee012093267b3376c079ec83"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-win32.whl", hash = "sha256:76a095cfe6045c7d0ca77db9934e8f7b71b14645f0094ffcd842349ada5c5fb9"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:b4f87d4ed9064b2628da63830986c3d2dca7501e6018347798313fcf028e2fd4"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fec03caabbc6b59ea4a638bee5fce7117be8e99a4103d9d5ad77f15d6f81020c"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c83f957782cbbe8136bee26416686a6ae998c7b6191711a04da776dc9e47d4"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009e6bb1f1935a62889ddc8541514b6a9e1fcf302667dcb049a0be5c8f613e56"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75fc59fc450050b1b3c203c35020bc41bd2695ed692a392924c6ce180c6f1dc9"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:782e2c9b2aab1708ffb07d4bf377d12901d7a1d99e5e410d648d892f8967ab1f"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-win32.whl", hash = "sha256:edb45bb8278574710e68a6b021599a10ce730d156e5b254941754a9cc0b17d03"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:e271058822765ad5e3bca7f05f2ace0de58a3f4e62045a8c90a0dfd2f8ad8cc6"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e98c8af98d5707dcdecc9ab0863c0ea6e88545d42ca7c3feffb6b4d1e370c7ba"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:952c81d415b9b80ea261d2372d2a4a2332a3890c2b83e0535f263ddfe43f0d43"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80b39d3a151309efc8cc48675918891b865bdf742a8616a337cb0090791a0de9"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e221060b701e2aa2ea991542900dd13907a5c90fa80e199dbf5a03359019e7a3"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:92f09ff65ecff3108e56526f9e2481b8116c0b9e1425325e13245abfd79bdb1b"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-win32.whl", hash = "sha256:3ad54b9ddbe20ae9f7c1b29e52f123120772b06dbb18ec6be9101369d63a4074"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:127a789c75151db6af398b8972178afe6bda7d6f68730c057fbbc2e96b08d282"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4ed0518a14dd26092614412936920ad081a424bdcb54cc13349a8e2c6d106a"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ad9e6ed739285919aa9661a5bbed0aaf410aa60231373c5579c6b4801bd883c"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc0a92c02fa1ca1e84fc60fa258458e5bf89d90a1ddaeb8ed9cc3147f417255"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0aefc7591920bbd360d57ea03c995cebc204b424524a5bd78406f6e1b8b2a5d8"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5faf03a7d8942bb4476e3b62fd0f4cf94eaf4618e304a19865abf89a35c0bbee"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-win32.whl", hash = "sha256:e333e2324307a7b5d86adfa835bb500ee70bfcd1447384a822e96495796b0ca4"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:cb73507defd385b7705c599a94474b1d5222a508e502553ef94114a143ec6696"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:366c32fe5355ef5fc8a232c5436f4cc66e9d3e8967c01fb2e6302fd6627e3d94"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2297f08f08a2bb0d32a4265e98a006643cd7233fb7983032bd61ac7a02956b3b"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18dd842b49456aaa9a7cf535b04ca4571a302ff72ed8740d06b5adcd41fe0757"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:217138197c170a2a74ca0e05bddcd5f1796c735c37d0eee33e43259b192aa424"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a3a87cf1e133e5b1994144c12ca4aa3d9698517fe1e2ca82977781b16955658"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-win32.whl", hash = "sha256:30b339b2a743c5288405aa79a69e706a06e02958eab31859f7f3c04980853b70"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:a899b10e17743683b293a729d3a11f2f399e8a90c73b089e29f5d0fe3509f0dd"}, - {file = "lazy_object_proxy-1.10.0-pp310.pp311.pp312.pp38.pp39-none-any.whl", hash = "sha256:80fa48bd89c8f2f456fc0765c11c23bf5af827febacd2f523ca5bc1893fcc09d"}, -] - [[package]] name = "macfsevents" version = "0.8.4" @@ -585,18 +586,15 @@ altgraph = ">=0.17" [[package]] name = "markdown" -version = "3.5.2" +version = "3.7" description = "Python implementation of John Gruber's Markdown." optional = false python-versions = ">=3.8" files = [ - {file = "Markdown-3.5.2-py3-none-any.whl", hash = "sha256:d43323865d89fc0cb9b20c75fc8ad313af307cc087e84b657d9eec768eddeadd"}, - {file = "Markdown-3.5.2.tar.gz", hash = "sha256:e1ac7b3dc550ee80e602e71c1d168002f062e49f1b11e26a36264dafd4df2ef8"}, + {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"}, + {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"}, ] -[package.dependencies] -importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} - [package.extras] docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] testing = ["coverage", "pyyaml"] @@ -694,86 +692,101 @@ files = [ [[package]] name = "minilog" -version = "2.3" +version = "2.3.1" description = "Minimalistic wrapper for Python logging." optional = false -python-versions = ">=3.8,<4.0" +python-versions = "<4.0,>=3.8" files = [ - {file = "minilog-2.3-py3-none-any.whl", hash = "sha256:e42dc2def1da424e90d6664279c128dde94adc5840557b27857957ed23ee09b6"}, - {file = "minilog-2.3.tar.gz", hash = "sha256:ebdf354f1dd86a2e8a824cdde4b7b50cdbc24b99a5465bc4d1806bd1e030bc92"}, + {file = "minilog-2.3.1-py3-none-any.whl", hash = "sha256:1a679fefe6140ce1d59c3246adc991f9eb480169e5a6c54d2be9023ee459dc30"}, + {file = "minilog-2.3.1.tar.gz", hash = "sha256:4b602572c3bcdd2d8f00d879f635c0de9e632d5d0307e131c91074be8acf444e"}, ] [[package]] name = "mkdocs" -version = "1.5.3" +version = "1.6.1" description = "Project documentation with Markdown." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"}, - {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"}, + {file = "mkdocs-1.6.1-py3-none-any.whl", hash = "sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e"}, + {file = "mkdocs-1.6.1.tar.gz", hash = "sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2"}, ] [package.dependencies] click = ">=7.0" colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} ghp-import = ">=1.0" -importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} jinja2 = ">=2.11.1" -markdown = ">=3.2.1" +markdown = ">=3.3.6" markupsafe = ">=2.0.1" mergedeep = ">=1.3.4" +mkdocs-get-deps = ">=0.2.0" packaging = ">=20.5" pathspec = ">=0.11.1" -platformdirs = ">=2.2.0" pyyaml = ">=5.1" pyyaml-env-tag = ">=0.1" watchdog = ">=2.0" [package.extras] i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] + +[[package]] +name = "mkdocs-get-deps" +version = "0.2.0" +description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, + {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, +] + +[package.dependencies] +mergedeep = ">=1.3.4" +platformdirs = ">=2.2.0" +pyyaml = ">=5.1" [[package]] name = "mypy" -version = "1.8.0" +version = "1.11.2" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:485a8942f671120f76afffff70f259e1cd0f0cfe08f81c05d8816d958d4577d3"}, - {file = "mypy-1.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:df9824ac11deaf007443e7ed2a4a26bebff98d2bc43c6da21b2b64185da011c4"}, - {file = "mypy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afecd6354bbfb6e0160f4e4ad9ba6e4e003b767dd80d85516e71f2e955ab50d"}, - {file = "mypy-1.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8963b83d53ee733a6e4196954502b33567ad07dfd74851f32be18eb932fb1cb9"}, - {file = "mypy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:e46f44b54ebddbeedbd3d5b289a893219065ef805d95094d16a0af6630f5d410"}, - {file = "mypy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:855fe27b80375e5c5878492f0729540db47b186509c98dae341254c8f45f42ae"}, - {file = "mypy-1.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4c886c6cce2d070bd7df4ec4a05a13ee20c0aa60cb587e8d1265b6c03cf91da3"}, - {file = "mypy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d19c413b3c07cbecf1f991e2221746b0d2a9410b59cb3f4fb9557f0365a1a817"}, - {file = "mypy-1.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9261ed810972061388918c83c3f5cd46079d875026ba97380f3e3978a72f503d"}, - {file = "mypy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:51720c776d148bad2372ca21ca29256ed483aa9a4cdefefcef49006dff2a6835"}, - {file = "mypy-1.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:52825b01f5c4c1c4eb0db253ec09c7aa17e1a7304d247c48b6f3599ef40db8bd"}, - {file = "mypy-1.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f5ac9a4eeb1ec0f1ccdc6f326bcdb464de5f80eb07fb38b5ddd7b0de6bc61e55"}, - {file = "mypy-1.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afe3fe972c645b4632c563d3f3eff1cdca2fa058f730df2b93a35e3b0c538218"}, - {file = "mypy-1.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:42c6680d256ab35637ef88891c6bd02514ccb7e1122133ac96055ff458f93fc3"}, - {file = "mypy-1.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:720a5ca70e136b675af3af63db533c1c8c9181314d207568bbe79051f122669e"}, - {file = "mypy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:028cf9f2cae89e202d7b6593cd98db6759379f17a319b5faf4f9978d7084cdc6"}, - {file = "mypy-1.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4e6d97288757e1ddba10dd9549ac27982e3e74a49d8d0179fc14d4365c7add66"}, - {file = "mypy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f1478736fcebb90f97e40aff11a5f253af890c845ee0c850fe80aa060a267c6"}, - {file = "mypy-1.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42419861b43e6962a649068a61f4a4839205a3ef525b858377a960b9e2de6e0d"}, - {file = "mypy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b5b6c721bd4aabaadead3a5e6fa85c11c6c795e0c81a7215776ef8afc66de02"}, - {file = "mypy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5c1538c38584029352878a0466f03a8ee7547d7bd9f641f57a0f3017a7c905b8"}, - {file = "mypy-1.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ef4be7baf08a203170f29e89d79064463b7fc7a0908b9d0d5114e8009c3a259"}, - {file = "mypy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178def594014aa6c35a8ff411cf37d682f428b3b5617ca79029d8ae72f5402b"}, - {file = "mypy-1.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ab3c84fa13c04aeeeabb2a7f67a25ef5d77ac9d6486ff33ded762ef353aa5592"}, - {file = "mypy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:99b00bc72855812a60d253420d8a2eae839b0afa4938f09f4d2aa9bb4654263a"}, - {file = "mypy-1.8.0-py3-none-any.whl", hash = "sha256:538fd81bb5e430cc1381a443971c0475582ff9f434c16cd46d2c66763ce85d9d"}, - {file = "mypy-1.8.0.tar.gz", hash = "sha256:6ff8b244d7085a0b425b56d327b480c3b29cafbd2eff27316a004f9a7391ae07"}, + {file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"}, + {file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"}, + {file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"}, + {file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"}, + {file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"}, + {file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"}, + {file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"}, + {file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"}, + {file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"}, + {file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"}, + {file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"}, + {file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"}, + {file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"}, + {file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"}, + {file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"}, + {file = "mypy-1.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:37c7fa6121c1cdfcaac97ce3d3b5588e847aa79b580c1e922bb5d5d2902df19b"}, + {file = "mypy-1.11.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a8a53bc3ffbd161b5b2a4fff2f0f1e23a33b0168f1c0778ec70e1a3d66deb86"}, + {file = "mypy-1.11.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ff93107f01968ed834f4256bc1fc4475e2fecf6c661260066a985b52741ddce"}, + {file = "mypy-1.11.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:edb91dded4df17eae4537668b23f0ff6baf3707683734b6a818d5b9d0c0c31a1"}, + {file = "mypy-1.11.2-cp38-cp38-win_amd64.whl", hash = "sha256:ee23de8530d99b6db0573c4ef4bd8f39a2a6f9b60655bf7a1357e585a3486f2b"}, + {file = "mypy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:801ca29f43d5acce85f8e999b1e431fb479cb02d0e11deb7d2abb56bdaf24fd6"}, + {file = "mypy-1.11.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af8d155170fcf87a2afb55b35dc1a0ac21df4431e7d96717621962e4b9192e70"}, + {file = "mypy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7821776e5c4286b6a13138cc935e2e9b6fde05e081bdebf5cdb2bb97c9df81d"}, + {file = "mypy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:539c570477a96a4e6fb718b8d5c3e0c0eba1f485df13f86d2970c91f0673148d"}, + {file = "mypy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f14cd3d386ac4d05c5a39a51b84387403dadbd936e17cb35882134d4f8f0d24"}, + {file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"}, + {file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.1.0" +typing-extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] @@ -806,13 +819,13 @@ files = [ [[package]] name = "openpyxl" -version = "3.1.2" +version = "3.1.5" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5"}, - {file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"}, + {file = "openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2"}, + {file = "openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"}, ] [package.dependencies] @@ -820,13 +833,13 @@ et-xmlfile = "*" [[package]] name = "packaging" -version = "23.2" +version = "24.1" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] [[package]] @@ -842,24 +855,24 @@ files = [ [[package]] name = "pefile" -version = "2023.2.7" +version = "2024.8.26" description = "Python PE parsing module" optional = false python-versions = ">=3.6.0" files = [ - {file = "pefile-2023.2.7-py3-none-any.whl", hash = "sha256:da185cd2af68c08a6cd4481f7325ed600a88f6a813bad9dea07ab3ef73d8d8d6"}, - {file = "pefile-2023.2.7.tar.gz", hash = "sha256:82e6114004b3d6911c77c3953e3838654b04511b8b66e8583db70c65998017dc"}, + {file = "pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f"}, + {file = "pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632"}, ] [[package]] name = "plantuml-markdown" -version = "3.9.3" +version = "3.10.3" description = "A PlantUML plugin for Markdown" optional = false python-versions = "*" files = [ - {file = "plantuml-markdown-3.9.3.tar.gz", hash = "sha256:5f7e34bfeee470069ba83e8e5cbde9156700d052788625ea14a029f3b244d3aa"}, - {file = "plantuml_markdown-3.9.3-py3-none-any.whl", hash = "sha256:eda3782cd77b50509feeabe48d7b094c28e5e7263e83bd05eeea9c2d1f455d3a"}, + {file = "plantuml-markdown-3.10.3.tar.gz", hash = "sha256:09c21bd2e3799eca11c2efe847e004e2ebca364758bf94d70b7d4d1081d5d581"}, + {file = "plantuml_markdown-3.10.3-py3-none-any.whl", hash = "sha256:5778fcb0b2f766cf1322b876e5de293e6c9a5d0367b774d93673aa4244381525"}, ] [package.dependencies] @@ -869,45 +882,35 @@ six = "*" [[package]] name = "platformdirs" -version = "4.2.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "4.2.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, - {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, ] [package.extras] docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] +type = ["mypy (>=1.8)"] [[package]] name = "pluggy" -version = "1.4.0" +version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ - {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, - {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] - [[package]] name = "pydocstyle" version = "6.3.0" @@ -927,87 +930,91 @@ toml = ["tomli (>=1.2.3)"] [[package]] name = "pygments" -version = "2.17.2" +version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, - {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, ] [package.extras] -plugins = ["importlib-metadata"] windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyinstaller" -version = "4.5.1" +version = "6.10.0" description = "PyInstaller bundles a Python application and all its dependencies into a single package." optional = false -python-versions = ">=3.6" +python-versions = "<3.14,>=3.8" files = [ - {file = "pyinstaller-4.5.1-py3-none-macosx_10_13_universal2.whl", hash = "sha256:ecc2baadeeefd2b6fbf39d13c65d4aa603afdda1c6aaaebc4577ba72893fee9e"}, - {file = "pyinstaller-4.5.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4d848cd782ee0893d7ad9fe2bfe535206a79f0b6760cecc5f2add831258b9322"}, - {file = "pyinstaller-4.5.1-py3-none-manylinux2014_i686.whl", hash = "sha256:8f747b190e6ad30e2d2fd5da9a64636f61aac8c038c0b7f685efa92c782ea14f"}, - {file = "pyinstaller-4.5.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c587da8f521a7ce1b9efb4e3d0117cd63c92dc6cedff24590aeef89372f53012"}, - {file = "pyinstaller-4.5.1-py3-none-win32.whl", hash = "sha256:fed9f5e4802769a416a8f2ca171c6be961d1861cc05a0b71d20dfe05423137e9"}, - {file = "pyinstaller-4.5.1-py3-none-win_amd64.whl", hash = "sha256:aae456205c68355f9597411090576bb31b614e53976b4c102d072bbe5db8392a"}, - {file = "pyinstaller-4.5.1.tar.gz", hash = "sha256:30733baaf8971902286a0ddf77e5499ac5f7bf8e7c39163e83d4f8c696ef265e"}, + {file = "pyinstaller-6.10.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:d60fb22859e11483af735aec115fdde09467cdbb29edd9844839f2c920b748c0"}, + {file = "pyinstaller-6.10.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:46d75359668993ddd98630a3669dc5249f3c446e35239b43bc7f4155bc574748"}, + {file = "pyinstaller-6.10.0-py3-none-manylinux2014_i686.whl", hash = "sha256:3398a98fa17d47ccb31f8779ecbdacec025f7adb2f22757a54b706ac8b4fe906"}, + {file = "pyinstaller-6.10.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e9989f354ae4ed8a3bec7bdb37ae0d170751d6520e500f049c7cd0632d31d5c3"}, + {file = "pyinstaller-6.10.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:b7c90c91921b3749083115b28f30f40abf2bb481ceff196d2b2ce0eaa2b3d429"}, + {file = "pyinstaller-6.10.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6cf876d7d93b8b4f28d1ad57fa24645cf43119c79e985dd5e5f7a801245e6f53"}, + {file = "pyinstaller-6.10.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:db05e3f2f10f9f78c56f1fb163d9cb453433429fe4281218ebaf1ebfd39ba942"}, + {file = "pyinstaller-6.10.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:28eca3817f176fdc19747e1afcf434f13bb9f17a644f611be2c5a61b1f498ed7"}, + {file = "pyinstaller-6.10.0-py3-none-win32.whl", hash = "sha256:703e041718987e46ba0568a2c71ecf2459fddef57cf9edf3efeed4a53e3dae3f"}, + {file = "pyinstaller-6.10.0-py3-none-win_amd64.whl", hash = "sha256:95b55966e563e8b8f31a43882aea10169e9a11fdf38e626d86a2907b640c0701"}, + {file = "pyinstaller-6.10.0-py3-none-win_arm64.whl", hash = "sha256:308e0a8670c9c9ac0cebbf1bbb492e71b6675606f2ec78bc4adfc830d209e087"}, + {file = "pyinstaller-6.10.0.tar.gz", hash = "sha256:143840f8056ff7b910bf8f16f6cd92cc10a6c2680bb76d0a25d558d543d21270"}, ] [package.dependencies] altgraph = "*" macholib = {version = ">=1.8", markers = "sys_platform == \"darwin\""} -pefile = {version = ">=2017.8.1", markers = "sys_platform == \"win32\""} -pyinstaller-hooks-contrib = ">=2020.6" -pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} -setuptools = "*" +packaging = ">=22.0" +pefile = {version = ">=2022.5.30", markers = "sys_platform == \"win32\""} +pyinstaller-hooks-contrib = ">=2024.8" +pywin32-ctypes = {version = ">=0.2.1", markers = "sys_platform == \"win32\""} +setuptools = ">=42.0.0" [package.extras] -encryption = ["tinyaes (>=1.0.0)"] +completion = ["argcomplete"] hook-testing = ["execnet (>=1.5.0)", "psutil", "pytest (>=2.7.3)"] [[package]] name = "pyinstaller-hooks-contrib" -version = "2024.1" +version = "2024.8" description = "Community maintained hooks for PyInstaller" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pyinstaller-hooks-contrib-2024.1.tar.gz", hash = "sha256:51a51ea9e1ae6bd5ffa7ec45eba7579624bf4f2472ff56dba0edc186f6ed46a6"}, - {file = "pyinstaller_hooks_contrib-2024.1-py2.py3-none-any.whl", hash = "sha256:131494f9cfce190aaa66ed82e82c78b2723d1720ce64d012fbaf938f4ab01d35"}, + {file = "pyinstaller_hooks_contrib-2024.8-py3-none-any.whl", hash = "sha256:0057fe9a5c398d3f580e73e58793a1d4a8315ca91c3df01efea1c14ed557825a"}, + {file = "pyinstaller_hooks_contrib-2024.8.tar.gz", hash = "sha256:29b68d878ab739e967055b56a93eb9b58e529d5b054fbab7a2f2bacf80cef3e2"}, ] [package.dependencies] -importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} packaging = ">=22.0" setuptools = ">=42.0.0" [[package]] name = "pylint" -version = "2.15.10" +version = "3.2.7" description = "python code static checker" optional = false -python-versions = ">=3.7.2" +python-versions = ">=3.8.0" files = [ - {file = "pylint-2.15.10-py3-none-any.whl", hash = "sha256:9df0d07e8948a1c3ffa3b6e2d7e6e63d9fb457c5da5b961ed63106594780cc7e"}, - {file = "pylint-2.15.10.tar.gz", hash = "sha256:b3dc5ef7d33858f297ac0d06cc73862f01e4f2e74025ec3eff347ce0bc60baf5"}, + {file = "pylint-3.2.7-py3-none-any.whl", hash = "sha256:02f4aedeac91be69fb3b4bea997ce580a4ac68ce58b89eaefeaf06749df73f4b"}, + {file = "pylint-3.2.7.tar.gz", hash = "sha256:1b7a721b575eaeaa7d39db076b6e7743c993ea44f57979127c517c6c572c803e"}, ] [package.dependencies] -astroid = ">=2.12.13,<=2.14.0-dev0" +astroid = ">=3.2.4,<=3.3.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, - {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, + {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, ] -isort = ">=4.2.5,<6" +isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} tomlkit = ">=0.10.1" -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] spelling = ["pyenchant (>=3.2,<4.0)"] @@ -1028,37 +1035,35 @@ python-dateutil = ">=2.0" [[package]] name = "pytest" -version = "6.2.5" +version = "8.3.2" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, - {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, + {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"}, + {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"}, ] [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -toml = "*" +pluggy = ">=1.5,<2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" -version = "4.1.0" +version = "5.0.0" description = "Pytest plugin for measuring coverage." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, - {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, + {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, + {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, ] [package.dependencies] @@ -1066,7 +1071,7 @@ coverage = {version = ">=5.2.1", extras = ["toml"]} pytest = ">=4.6" [package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pytest-expecter" @@ -1100,13 +1105,13 @@ dev = ["black", "flake8", "pre-commit"] [[package]] name = "python-dateutil" -version = "2.8.2" +version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] [package.dependencies] @@ -1157,73 +1162,75 @@ setuptools = "*" [[package]] name = "pywin32-ctypes" -version = "0.2.2" +version = "0.2.3" description = "A (partial) reimplementation of pywin32 using ctypes/cffi" optional = false python-versions = ">=3.6" files = [ - {file = "pywin32-ctypes-0.2.2.tar.gz", hash = "sha256:3426e063bdd5fd4df74a14fa3cf80a0b42845a87e1d1e81f6549f9daec593a60"}, - {file = "pywin32_ctypes-0.2.2-py3-none-any.whl", hash = "sha256:bf490a1a709baf35d688fe0ecf980ed4de11d2b3e37b51e5442587a75d9957e7"}, + {file = "pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755"}, + {file = "pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8"}, ] [[package]] name = "pyyaml" -version = "6.0.1" +version = "6.0.2" description = "YAML parser and emitter for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, ] [[package]] @@ -1242,13 +1249,13 @@ pyyaml = "*" [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -1275,19 +1282,23 @@ files = [ [[package]] name = "setuptools" -version = "69.1.1" +version = "74.1.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"}, - {file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"}, + {file = "setuptools-74.1.2-py3-none-any.whl", hash = "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308"}, + {file = "setuptools-74.1.2.tar.gz", hash = "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.11.*)", "pytest-mypy"] [[package]] name = "six" @@ -1335,13 +1346,13 @@ files = [ [[package]] name = "soupsieve" -version = "2.5" +version = "2.6" description = "A modern CSS selector implementation for Beautiful Soup." optional = false python-versions = ">=3.8" files = [ - {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, - {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, + {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, + {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, ] [[package]] @@ -1358,17 +1369,6 @@ files = [ [package.extras] tests = ["pytest", "pytest-cov"] -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - [[package]] name = "tomli" version = "2.0.1" @@ -1382,46 +1382,46 @@ files = [ [[package]] name = "tomlkit" -version = "0.12.3" +version = "0.13.2" description = "Style preserving TOML library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomlkit-0.12.3-py3-none-any.whl", hash = "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"}, - {file = "tomlkit-0.12.3.tar.gz", hash = "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4"}, + {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, + {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, ] [[package]] name = "types-markdown" -version = "3.5.0.20240129" +version = "3.7.0.20240822" description = "Typing stubs for Markdown" optional = false python-versions = ">=3.8" files = [ - {file = "types-Markdown-3.5.0.20240129.tar.gz", hash = "sha256:9acd36fef264d9ed5a96345c45f7d80f0d967059e92213998b3046fbb64f67fc"}, - {file = "types_Markdown-3.5.0.20240129-py3-none-any.whl", hash = "sha256:d6861d9d68e8268a5346d8a43d14727e6c636ebc6d49f2b8fc034c25996d35dd"}, + {file = "types-Markdown-3.7.0.20240822.tar.gz", hash = "sha256:183557c9f4f865bdefd8f5f96a38145c31819271cde111d35557c3bd2069e78d"}, + {file = "types_Markdown-3.7.0.20240822-py3-none-any.whl", hash = "sha256:bec91c410aaf2470ffdb103e38438fbcc53689b00133f19e64869eb138432ad7"}, ] [[package]] name = "types-pyyaml" -version = "6.0.12.12" +version = "6.0.12.20240808" description = "Typing stubs for PyYAML" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "types-PyYAML-6.0.12.12.tar.gz", hash = "sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062"}, - {file = "types_PyYAML-6.0.12.12-py3-none-any.whl", hash = "sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24"}, + {file = "types-PyYAML-6.0.12.20240808.tar.gz", hash = "sha256:b8f76ddbd7f65440a8bda5526a9607e4c7a322dc2f8e1a8c405644f9a6f4b9af"}, + {file = "types_PyYAML-6.0.12.20240808-py3-none-any.whl", hash = "sha256:deda34c5c655265fc517b546c902aa6eed2ef8d3e921e4765fe606fe2afe8d35"}, ] [[package]] name = "types-requests" -version = "2.31.0.20240218" +version = "2.32.0.20240905" description = "Typing stubs for requests" optional = false python-versions = ">=3.8" files = [ - {file = "types-requests-2.31.0.20240218.tar.gz", hash = "sha256:f1721dba8385958f504a5386240b92de4734e047a08a40751c1654d1ac3349c5"}, - {file = "types_requests-2.31.0.20240218-py3-none-any.whl", hash = "sha256:a82807ec6ddce8f00fe0e949da6d6bc1fbf1715420218a9640d695f70a9e5a9b"}, + {file = "types-requests-2.32.0.20240905.tar.gz", hash = "sha256:e97fd015a5ed982c9ddcd14cc4afba9d111e0e06b797c8f776d14602735e9bd6"}, + {file = "types_requests-2.32.0.20240905-py3-none-any.whl", hash = "sha256:f46ecb55f5e1a37a58be684cf3f013f166da27552732ef2469a0cc8e62a72881"}, ] [package.dependencies] @@ -1429,35 +1429,35 @@ urllib3 = ">=2" [[package]] name = "types-setuptools" -version = "69.1.0.20240223" +version = "74.0.0.20240831" description = "Typing stubs for setuptools" optional = false python-versions = ">=3.8" files = [ - {file = "types-setuptools-69.1.0.20240223.tar.gz", hash = "sha256:8a886a1fd06b668782dfbdaded4fd8a4e8c9f3d8d4c02acdd1240df098f50bf7"}, - {file = "types_setuptools-69.1.0.20240223-py3-none-any.whl", hash = "sha256:30a0d9903a81a424bd0f979534552a016a4543760aaffd499b9a2fe85bae0bfd"}, + {file = "types-setuptools-74.0.0.20240831.tar.gz", hash = "sha256:8b4a544cc91d42a019dc1e41fd397608b4bc7e20c7d7d5bc326589ffd9e8f8a1"}, + {file = "types_setuptools-74.0.0.20240831-py3-none-any.whl", hash = "sha256:4d9d18ea9214828d695a384633130009f5dee2681a157ee873d3680b62931590"}, ] [[package]] name = "typing-extensions" -version = "4.10.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, - {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] name = "urllib3" -version = "2.2.1" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] @@ -1483,40 +1483,41 @@ testing = ["coverage (>=5.0)", "pytest", "pytest-cov"] [[package]] name = "watchdog" -version = "4.0.0" +version = "5.0.2" description = "Filesystem events monitoring" optional = false -python-versions = ">=3.8" -files = [ - {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:39cb34b1f1afbf23e9562501673e7146777efe95da24fab5707b88f7fb11649b"}, - {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c522392acc5e962bcac3b22b9592493ffd06d1fc5d755954e6be9f4990de932b"}, - {file = "watchdog-4.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c47bdd680009b11c9ac382163e05ca43baf4127954c5f6d0250e7d772d2b80c"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8350d4055505412a426b6ad8c521bc7d367d1637a762c70fdd93a3a0d595990b"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:11e12fafb13372e18ca1bbf12d50f593e7280646687463dd47730fd4f4d5d257"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5369136a6474678e02426bd984466343924d1df8e2fd94a9b443cb7e3aa20d19"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76ad8484379695f3fe46228962017a7e1337e9acadafed67eb20aabb175df98b"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:45cc09cc4c3b43fb10b59ef4d07318d9a3ecdbff03abd2e36e77b6dd9f9a5c85"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eed82cdf79cd7f0232e2fdc1ad05b06a5e102a43e331f7d041e5f0e0a34a51c4"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba30a896166f0fee83183cec913298151b73164160d965af2e93a20bbd2ab605"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d18d7f18a47de6863cd480734613502904611730f8def45fc52a5d97503e5101"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2895bf0518361a9728773083908801a376743bcc37dfa252b801af8fd281b1ca"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87e9df830022488e235dd601478c15ad73a0389628588ba0b028cb74eb72fed8"}, - {file = "watchdog-4.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6e949a8a94186bced05b6508faa61b7adacc911115664ccb1923b9ad1f1ccf7b"}, - {file = "watchdog-4.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6a4db54edea37d1058b08947c789a2354ee02972ed5d1e0dca9b0b820f4c7f92"}, - {file = "watchdog-4.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d31481ccf4694a8416b681544c23bd271f5a123162ab603c7d7d2dd7dd901a07"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:6a9c71a0b02985b4b0b6d14b875a6c86ddea2fdbebd0c9a720a806a8bbffc69f"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:557ba04c816d23ce98a06e70af6abaa0485f6d94994ec78a42b05d1c03dcbd50"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:d0f9bd1fd919134d459d8abf954f63886745f4660ef66480b9d753a7c9d40927"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f9b2fdca47dc855516b2d66eef3c39f2672cbf7e7a42e7e67ad2cbfcd6ba107d"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:73c7a935e62033bd5e8f0da33a4dcb763da2361921a69a5a95aaf6c93aa03a87"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269"}, - {file = "watchdog-4.0.0-py3-none-win32.whl", hash = "sha256:8f9a542c979df62098ae9c58b19e03ad3df1c9d8c6895d96c0d51da17b243b1c"}, - {file = "watchdog-4.0.0-py3-none-win_amd64.whl", hash = "sha256:f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245"}, - {file = "watchdog-4.0.0-py3-none-win_ia64.whl", hash = "sha256:9a03e16e55465177d416699331b0f3564138f1807ecc5f2de9d55d8f188d08c7"}, - {file = "watchdog-4.0.0.tar.gz", hash = "sha256:e3e7065cbdabe6183ab82199d7a4f6b3ba0a438c5a512a68559846ccb76a78ec"}, +python-versions = ">=3.9" +files = [ + {file = "watchdog-5.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d961f4123bb3c447d9fcdcb67e1530c366f10ab3a0c7d1c0c9943050936d4877"}, + {file = "watchdog-5.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72990192cb63872c47d5e5fefe230a401b87fd59d257ee577d61c9e5564c62e5"}, + {file = "watchdog-5.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6bec703ad90b35a848e05e1b40bf0050da7ca28ead7ac4be724ae5ac2653a1a0"}, + {file = "watchdog-5.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:dae7a1879918f6544201d33666909b040a46421054a50e0f773e0d870ed7438d"}, + {file = "watchdog-5.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c4a440f725f3b99133de610bfec93d570b13826f89616377715b9cd60424db6e"}, + {file = "watchdog-5.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8b2918c19e0d48f5f20df458c84692e2a054f02d9df25e6c3c930063eca64c1"}, + {file = "watchdog-5.0.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:aa9cd6e24126d4afb3752a3e70fce39f92d0e1a58a236ddf6ee823ff7dba28ee"}, + {file = "watchdog-5.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f627c5bf5759fdd90195b0c0431f99cff4867d212a67b384442c51136a098ed7"}, + {file = "watchdog-5.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d7594a6d32cda2b49df3fd9abf9b37c8d2f3eab5df45c24056b4a671ac661619"}, + {file = "watchdog-5.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba32efcccfe2c58f4d01115440d1672b4eb26cdd6fc5b5818f1fb41f7c3e1889"}, + {file = "watchdog-5.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:963f7c4c91e3f51c998eeff1b3fb24a52a8a34da4f956e470f4b068bb47b78ee"}, + {file = "watchdog-5.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8c47150aa12f775e22efff1eee9f0f6beee542a7aa1a985c271b1997d340184f"}, + {file = "watchdog-5.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:14dd4ed023d79d1f670aa659f449bcd2733c33a35c8ffd88689d9d243885198b"}, + {file = "watchdog-5.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b84bff0391ad4abe25c2740c7aec0e3de316fdf7764007f41e248422a7760a7f"}, + {file = "watchdog-5.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e8d5ff39f0a9968952cce548e8e08f849141a4fcc1290b1c17c032ba697b9d7"}, + {file = "watchdog-5.0.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fb223456db6e5f7bd9bbd5cd969f05aae82ae21acc00643b60d81c770abd402b"}, + {file = "watchdog-5.0.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9814adb768c23727a27792c77812cf4e2fd9853cd280eafa2bcfa62a99e8bd6e"}, + {file = "watchdog-5.0.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:901ee48c23f70193d1a7bc2d9ee297df66081dd5f46f0ca011be4f70dec80dab"}, + {file = "watchdog-5.0.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:638bcca3d5b1885c6ec47be67bf712b00a9ab3d4b22ec0881f4889ad870bc7e8"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:5597c051587f8757798216f2485e85eac583c3b343e9aa09127a3a6f82c65ee8"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_armv7l.whl", hash = "sha256:53ed1bf71fcb8475dd0ef4912ab139c294c87b903724b6f4a8bd98e026862e6d"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_i686.whl", hash = "sha256:29e4a2607bd407d9552c502d38b45a05ec26a8e40cc7e94db9bb48f861fa5abc"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_ppc64.whl", hash = "sha256:b6dc8f1d770a8280997e4beae7b9a75a33b268c59e033e72c8a10990097e5fde"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:d2ab34adc9bf1489452965cdb16a924e97d4452fcf88a50b21859068b50b5c3b"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_s390x.whl", hash = "sha256:7d1aa7e4bb0f0c65a1a91ba37c10e19dabf7eaaa282c5787e51371f090748f4b"}, + {file = "watchdog-5.0.2-py3-none-manylinux2014_x86_64.whl", hash = "sha256:726eef8f8c634ac6584f86c9c53353a010d9f311f6c15a034f3800a7a891d941"}, + {file = "watchdog-5.0.2-py3-none-win32.whl", hash = "sha256:bda40c57115684d0216556671875e008279dea2dc00fcd3dde126ac8e0d7a2fb"}, + {file = "watchdog-5.0.2-py3-none-win_amd64.whl", hash = "sha256:d010be060c996db725fbce7e3ef14687cdcc76f4ca0e4339a68cc4532c382a73"}, + {file = "watchdog-5.0.2-py3-none-win_ia64.whl", hash = "sha256:3960136b2b619510569b90f0cd96408591d6c251a75c97690f4553ca88889769"}, + {file = "watchdog-5.0.2.tar.gz", hash = "sha256:dcebf7e475001d2cdeb020be630dc5b687e9acdd60d16fea6bb4508e7b94cf76"}, ] [package.extras] @@ -1524,13 +1525,13 @@ watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "webob" -version = "1.8.7" +version = "1.8.8" description = "WSGI request and response object" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "WebOb-1.8.7-py2.py3-none-any.whl", hash = "sha256:73aae30359291c14fa3b956f8b5ca31960e420c28c1bec002547fb04928cf89b"}, - {file = "WebOb-1.8.7.tar.gz", hash = "sha256:b64ef5141be559cfade448f044fa45c2260351edcb6a8ef6b7e00c7dcef0c323"}, + {file = "WebOb-1.8.8-py2.py3-none-any.whl", hash = "sha256:b60ba63f05c0cf61e086a10c3781a41fcfe30027753a8ae6d819c77592ce83ea"}, + {file = "webob-1.8.8.tar.gz", hash = "sha256:2abc1555e118fc251e705fc6dc66c7f5353bb9fbfab6d20e22f1c02b4b71bcee"}, ] [package.extras] @@ -1557,101 +1558,7 @@ WebOb = ">=1.2" docs = ["Sphinx (>=1.8.1)", "docutils", "pylons-sphinx-themes (>=1.0.8)"] tests = ["PasteDeploy", "WSGIProxy2", "coverage", "pyquery", "pytest", "pytest-cov"] -[[package]] -name = "wrapt" -version = "1.16.0" -description = "Module for decorators, wrappers and monkey patching." -optional = false -python-versions = ">=3.6" -files = [ - {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, - {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, - {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, - {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, - {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, - {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, - {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, - {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, - {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, - {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, - {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, - {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, - {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, - {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, - {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, - {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, - {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, - {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, -] - -[[package]] -name = "zipp" -version = "3.17.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.8" -files = [ - {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, - {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - [metadata] lock-version = "2.0" -python-versions = "^3.8.10" -content-hash = "6e4701467c00912400e8f20e6b3ecc66f5962de055dd12e6fd397856385612c8" +python-versions = "^3.10" +content-hash = "ee7cbdb197e9ec82dec5864df0ddcad8c15ef0881b38ec1836b85113f0e0218c" diff --git a/pyproject.toml b/pyproject.toml index b5da88736..ad50f728f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "doorstop" -version = "3.0b15" +version = "3.0b16+codethink.0.3" description = "Requirements management using version control." license = "LGPLv3" @@ -32,7 +32,6 @@ classifiers = [ "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -44,7 +43,7 @@ classifiers = [ [tool.poetry.dependencies] -python = "^3.8.10" +python = "^3.10" pyyaml = "^6.0" markdown = "^3.3.3" @@ -55,24 +54,26 @@ python-markdown-math = "~0.6" plantuml-markdown = "^3.4.2" six = "*" # fixes https://github.com/dougn/python-plantuml/issues/11 openpyxl = ">=3.1.2" +setuptools = { version = ">=70", python = ">=3.12" } +dulwich = "^0.22.1" [tool.poetry.dev-dependencies] # Formatters -black = "^23.1" +black = "^24.3" isort = "^5.12" # Linters mypy = "^1.1.1" pydocstyle = "*" -pylint = "~2.15" +pylint = "~3.2" types-markdown = "*" types-pyyaml = "*" types-requests = "*" types-setuptools = "*" # Testing -pytest = "^6.2.5" +pytest = ">=7.2.0" pytest-cov = "*" pytest-expecter = "*" pytest-sugar = "*" @@ -87,7 +88,7 @@ mkdocs = "^1.5" pygments = "*" # Tooling -pyinstaller = "*" +pyinstaller = { version = ">=6", python = "<=3.13" } sniffer = "*" macfsevents = { version = "*", platform = "darwin" } pync = { version = "*", platform = "darwin" } @@ -109,5 +110,5 @@ profile = "black" [build-system] -requires = ["poetry>=0.12"] +requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" diff --git a/reqs/ext/.doorstop.yml b/reqs/ext/.doorstop.yml new file mode 100644 index 000000000..090108289 --- /dev/null +++ b/reqs/ext/.doorstop.yml @@ -0,0 +1,9 @@ +settings: + digits: 3 + itemformat: yaml + parent: REQ + prefix: EXT + sep: "" +extensions: + item_validator: .req_sha_item_validator.py + item_sha_required: true diff --git a/reqs/ext/.req_sha_item_validator.py b/reqs/ext/.req_sha_item_validator.py new file mode 100644 index 000000000..3012029e3 --- /dev/null +++ b/reqs/ext/.req_sha_item_validator.py @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: LGPL-3.0-only +from doorstop import DoorstopInfo, DoorstopWarning, DoorstopError +from subprocess import check_output +from copy import copy +from random import random + + +def item_validator(item): + if getattr(item, "references") == None: + return [] + + for ref in item.references: + if ref['sha'] != item._hash_reference(ref['path']): + yield DoorstopWarning("Hash has changed and it was not reviewed properly") + + if 'modified' in ref['path']: + temp_item = copy(item) + current_value = item.is_reviewed() + check_output( + "echo '1111' > $(git rev-parse --show-toplevel)/reqs/ext/test-modified.file", shell=True) + temp_item.review() + next_value = item.is_reviewed() + check_output( + "echo '0000' > $(git rev-parse --show-toplevel)/reqs/ext/test-modified.file", shell=True) + + yield DoorstopWarning(f"""This is a demonstration of a validator per folder identifying a external ref modified + without a proper review current SHA {current_value} modified SHA {next_value }. + Result: { next_value == current_value} """) diff --git a/reqs/ext/EXT001.yml b/reqs/ext/EXT001.yml new file mode 100644 index 000000000..b86847a72 --- /dev/null +++ b/reqs/ext/EXT001.yml @@ -0,0 +1,14 @@ +active: true +derived: false +header: '' +level: 1.0 +links: [] +normative: true +ref: '' +references: +- path: reqs/ext/test.file + sha: 24d9b35c727e6c78676c2ad378a8c3c47cfb539f3583d3cd9e1eafee51d5679d + type: file +reviewed: n0xxAj0z-SqNcebKEu8p9HDE8jAs5I8Vz4kX-5ZieA4= +text: | + Test where we calculate the SHA diff --git a/reqs/ext/EXT002.yml b/reqs/ext/EXT002.yml new file mode 100644 index 000000000..80989fdd2 --- /dev/null +++ b/reqs/ext/EXT002.yml @@ -0,0 +1,14 @@ +active: true +derived: false +header: '' +level: 2.0 +links: [] +normative: true +ref: '' +references: +- path: reqs/ext/test-modified.file + sha: 49ca5d81054fdd20572294b9350b605d05e0df91da09a46fb8bde7fd6c1c172d + type: file +reviewed: arLWz1tqET94t2j7FG0ncvKpwGe5twDi-jPbBnikxho= +text: | + Test where we calculate the SHA, file modified during evaluation diff --git a/reqs/ext/test-modified.file b/reqs/ext/test-modified.file new file mode 100644 index 000000000..739d79706 --- /dev/null +++ b/reqs/ext/test-modified.file @@ -0,0 +1 @@ +0000 diff --git a/reqs/ext/test.file b/reqs/ext/test.file new file mode 100644 index 000000000..635047563 --- /dev/null +++ b/reqs/ext/test.file @@ -0,0 +1 @@ +0001