diff --git a/.flake8 b/.flake8 index be7d44f..3db2a82 100644 --- a/.flake8 +++ b/.flake8 @@ -1,19 +1,33 @@ [flake8] +min_python_version = 3.7.0 max-line-length = 88 -ignore = E501, E203, W503 +ban-relative-imports = true +# flake8-use-fstring: https://github.com/MichaelKim0407/flake8-use-fstring#--percent-greedy-and---format-greedy +format-greedy = 1 +inline-quotes = double +# Allow omission of a return type hint for __init__ if at least one argument is annotated +# used by flake8-annotations +mypy-init-return = true +enable-extensions = TC, TC1 +type-checking-exempt-modules = typing, typing-extensions +eradicate-whitelist-extend = ^-.*; +extend-ignore = + # E203: Whitespace before ':' (pycqa/pycodestyle#373) + E203, + # SIM106: Handle error-cases first + SIM106, + # ANN101: Missing type annotation for self in method + ANN101, + # ANN102: Missing type annotation for cls in classmethod + ANN102, per-file-ignores = - __init__.py:F401 -exclude = - .git - __pycache__ - setup.py - build - dist - releases - .venv - .tox - .mypy_cache - .pytest_cache - .vscode - .github - tests/fixtures/ + # F401: Module imported by unused (non-implicit modules) + # TC002: Move third-party import '...' into a type-checking block + __init__.py:F401,TC002, + # ANN201: Missing return type annotation for public function + tests/test_*:ANN201 + tests/**/test_*:ANN201 +extend-exclude = + # External to the project's coding standards: + tests/fixtures/*, + tests/**/fixtures/*, diff --git a/.github/workflows/code-quality.yaml b/.github/workflows/code-quality.yaml deleted file mode 100644 index 7dab486..0000000 --- a/.github/workflows/code-quality.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: Code Quality - -on: - pull_request: - paths-ignore: - - 'docs/**' - push: - branches: [main] - paths-ignore: - - 'docs/**' - -jobs: - pre-commit: - name: Linting - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - - uses: pre-commit/action@v2.0.0 diff --git a/.github/workflows/tests.yml b/.github/workflows/main.yml similarity index 61% rename from .github/workflows/tests.yml rename to .github/workflows/main.yml index 084a29e..3ffff8e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/main.yml @@ -3,28 +3,33 @@ name: Tests on: pull_request: {} push: - branches: [main] + branches: + - main + + +concurrency: + group: tests-${{ github.head_ref || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: tests: - name: ${{ matrix.os }} / ${{ matrix.python-version }} - runs-on: "${{ matrix.os }}-latest" - continue-on-error: ${{ matrix.experimental }} + name: ${{ matrix.os }} / ${{ matrix.python-version }} ${{ matrix.suffix }} + runs-on: ${{ matrix.image }} strategy: matrix: - os: [Ubuntu, MacOS, Windows] - python-version: [3.6, 3.7, 3.8, 3.9] - experimental: [false] - bootstrap-args: [""] + os: [Ubuntu, macOS, Windows] + python-version: ["3.7", "3.8", "3.9", "3.10"] include: - os: Ubuntu - python-version: pypy3 - experimental: false - - os: Ubuntu - python-version: "3.10.0-alpha - 3.10.0" - experimental: true - bootstrap-args: "--git https://github.com/python-poetry/poetry.git" + image: ubuntu-latest + - os: Windows + image: windows-2022 + - os: macOS + image: macos-11 fail-fast: false + defaults: + run: + shell: bash steps: - uses: actions/checkout@v2 @@ -35,26 +40,21 @@ jobs: - name: Get full Python version id: full-python-version - shell: bash run: echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info))") - name: Bootstrap poetry - shell: bash run: | - curl -sL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py \ - | python - -y ${{ matrix.bootstrap-args }} + curl -sL https://install.python-poetry.org | python - -y ${{ matrix.bootstrap-args }} + - name: Update PATH if: ${{ matrix.os != 'Windows' }} - shell: bash run: echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Update Path for Windows if: ${{ matrix.os == 'Windows' }} - shell: bash run: echo "$APPDATA\Python\Scripts" >> $GITHUB_PATH - name: Configure poetry - shell: bash run: poetry config virtualenvs.in-project true - name: Set up cache @@ -66,13 +66,13 @@ jobs: - name: Ensure cache is healthy if: steps.cache.outputs.cache-hit == 'true' - shell: bash run: timeout 10s poetry run pip --version || rm -rf .venv - name: Install dependencies - shell: bash run: poetry install + - name: Install pytest plugin + run: poetry run pip install pytest-github-actions-annotate-failures + - name: Run pytest - shell: bash - run: poetry run python -m pytest -q tests/ + run: poetry run python -m pytest -p no:sugar -q tests/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9aa34bc..9311053 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,17 +6,13 @@ on: - '*.*.*' jobs: - Release: + release: + name: Release runs-on: ubuntu-latest - steps: - name: Checkout code uses: actions/checkout@v2 - - name: Get tag - id: tag - run: echo ::set-output name=tag::${GITHUB_REF#refs/tags/} - - name: Set up Python 3.9 uses: actions/setup-python@v2 with: @@ -24,8 +20,8 @@ jobs: - name: Install Poetry run: | - curl -sL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py \ - | python - -y + curl -sL https://install.python-poetry.org | python - -y ${{ matrix.bootstrap-args }} + - name: Update PATH run: echo "$HOME/.local/bin" >> $GITHUB_PATH @@ -37,6 +33,7 @@ jobs: run: | [[ "$(poetry version --short)" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] \ || echo ::set-output name=prerelease::true + - name: Create Release uses: ncipollo/release-action@v1 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 977f9bc..e339ec4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,29 +1,95 @@ +ci: + autofix_prs: false + repos: - - repo: https://github.com/psf/black - rev: 21.11b1 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.1.0 hooks: - - id: black + - id: trailing-whitespace + - id: end-of-file-fixer + exclude: ^.*\.egg-info/ + - id: check-merge-conflict + - id: check-case-conflict + - id: check-json + - id: check-toml + - id: check-yaml + - id: pretty-format-json + args: [--autofix, --no-ensure-ascii, --no-sort-keys] + - id: check-ast + - id: debug-statements + - id: check-docstring-first - - repo: https://gitlab.com/pycqa/flake8 - rev: 3.9.2 + - repo: https://github.com/pre-commit/pygrep-hooks + rev: v1.9.0 hooks: - - id: flake8 + - id: python-check-mock-methods + - id: python-use-type-annotations + - id: python-check-blanket-type-ignore + - id: python-check-blanket-noqa - - repo: https://github.com/timothycrosley/isort - rev: 5.10.1 + - repo: https://github.com/asottile/yesqa + rev: v1.3.0 hooks: - - id: isort - additional_dependencies: [toml] - exclude: ^.*/?setup\.py$ + - id: yesqa + additional_dependencies: &flake8_deps + - flake8-annotations==2.7.0 + - flake8-broken-line==0.4.0 + - flake8-bugbear==21.9.2 + - flake8-comprehensions==3.7.0 + - flake8-eradicate==1.2.0 + - flake8-no-pep420==1.2.0 + - flake8-quotes==3.3.1 + - flake8-simplify==0.14.2 + - flake8-tidy-imports==4.5.0 + - flake8-type-checking==1.1.0 + - flake8-typing-imports==1.11.0 + - flake8-use-fstring==1.3 + - pep8-naming==0.12.1 - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + - repo: https://github.com/asottile/pyupgrade + rev: v2.31.1 hooks: - - id: trailing-whitespace + - id: pyupgrade + args: [--py37-plus] + exclude: ^(install|get)-poetry.py$ + + - repo: https://github.com/pycqa/isort + rev: 5.10.1 + hooks: + - id: isort + name: "isort (python)" + types: [python] + args: [--add-import, from __future__ import annotations] exclude: | (?x)( - ^tests/.*/fixtures/.* + ^(install|get)-poetry.py$ + | ^src/poetry/__init__.py$ ) - - id: end-of-file-fixer - exclude: ^tests/.*/fixtures/.* - - id: debug-statements + - id: isort + name: "isort (pyi)" + types: [pyi] + args: [--lines-after-imports, "-1"] + + - repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + + - repo: https://github.com/pycqa/flake8 + rev: 4.0.1 + hooks: + - id: flake8 + additional_dependencies: *flake8_deps + + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v0.942 + hooks: + - id: mypy + pass_filenames: false + additional_dependencies: + - types-requests + + - repo: https://github.com/pre-commit/pre-commit + rev: v2.18.1 + hooks: + - id: validate_manifest diff --git a/README.md b/README.md index 2d08545..9c8b573 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Poetry export plugin +# Poetry Plugin: Export This package is a plugin that allows the export of locked packages to various formats. @@ -12,19 +12,19 @@ This plugin provides the same features as the existing `export` command of Poetr The easiest way to install the `export` plugin is via the `plugin add` command of Poetry. ```bash -poetry plugin add poetry-export-plugin +poetry plugin add poetry-plugin-export ``` If you used `pipx` to install Poetry you can add the plugin via the `pipx inject` command. ```bash -pipx inject poetry poetry-export-plugin +pipx inject poetry poetry-plugin-export ``` Otherwise, if you used `pip` to install Poetry you can add the plugin packages via the `pip install` command. ```bash -pip install poetry-export-plugin +pip install poetry-plugin-export ``` diff --git a/poetry.lock b/poetry.lock index b4316bf..787235b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,11 +1,3 @@ -[[package]] -name = "appdirs" -version = "1.4.4" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "main" -optional = false -python-versions = "*" - [[package]] name = "atomicwrites" version = "1.4.0" @@ -16,54 +8,25 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" -version = "21.2.0" +version = "21.4.0" description = "Classes Without Boilerplate" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] - -[[package]] -name = "black" -version = "21.8b0" -description = "The uncompromising code formatter." -category = "dev" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -click = ">=7.1.2" -dataclasses = {version = ">=0.6", markers = "python_version < \"3.7\""} -mypy-extensions = ">=0.4.3" -pathspec = ">=0.9.0,<1" -platformdirs = ">=2" -regex = ">=2020.1.8" -tomli = ">=0.2.6,<2.0.0" -typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\""} -typing-extensions = [ - {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, - {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, -] - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.6.0)", "aiohttp-cors (>=0.4.0)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -python2 = ["typed-ast (>=1.4.2)"] -uvloop = ["uvloop (>=0.15.2)"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] [[package]] name = "cachecontrol" -version = "0.12.6" +version = "0.12.10" description = "httplib2 caching for requests" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.6" [package.dependencies] lockfile = {version = ">=0.9", optional = true, markers = "extra == \"filecache\""} @@ -89,7 +52,7 @@ msgpack = ["msgpack-python (>=0.5,<0.6)"] [[package]] name = "certifi" -version = "2021.5.30" +version = "2021.10.8" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -97,7 +60,7 @@ python-versions = "*" [[package]] name = "cffi" -version = "1.14.6" +version = "1.15.0" description = "Foreign Function Interface for Python calling C code." category = "main" optional = false @@ -116,7 +79,7 @@ python-versions = ">=3.6.1" [[package]] name = "charset-normalizer" -version = "2.0.4" +version = "2.0.12" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false @@ -137,18 +100,6 @@ python-versions = ">=3.6,<4.0" crashtest = ">=0.3.1,<0.4.0" pylev = ">=1.3.0,<2.0.0" -[[package]] -name = "click" -version = "8.0.1" -description = "Composable command line interface toolkit" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} - [[package]] name = "colorama" version = "0.4.4" @@ -167,7 +118,7 @@ python-versions = ">=3.6,<4.0" [[package]] name = "cryptography" -version = "3.4.8" +version = "36.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "main" optional = false @@ -178,23 +129,15 @@ cffi = ">=1.12" [package.extras] docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] -docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] +docstest = ["pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] -sdist = ["setuptools-rust (>=0.11.4)"] +sdist = ["setuptools_rust (>=0.11.4)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["pytest (>=6.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] - -[[package]] -name = "dataclasses" -version = "0.8" -description = "A backport of the dataclasses module for Python 3.6" -category = "main" -optional = false -python-versions = ">=3.6, <3.7" +test = ["pytest (>=6.2.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] [[package]] name = "distlib" -version = "0.3.2" +version = "0.3.4" description = "Distribution utilities" category = "main" optional = false @@ -210,11 +153,15 @@ python-versions = ">=2.7" [[package]] name = "filelock" -version = "3.0.12" +version = "3.6.0" description = "A platform independent file lock." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] +testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] [[package]] name = "html5lib" @@ -236,18 +183,18 @@ lxml = ["lxml"] [[package]] name = "identify" -version = "2.2.13" +version = "2.4.12" description = "File identification library for Python" category = "dev" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.7" [package.extras] -license = ["editdistance-s"] +license = ["ukkonen"] [[package]] name = "idna" -version = "3.2" +version = "3.3" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false @@ -255,33 +202,20 @@ python-versions = ">=3.5" [[package]] name = "importlib-metadata" -version = "1.7.0" +version = "4.11.3" description = "Read metadata from Python packages" category = "main" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.7" [package.dependencies] +typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] -docs = ["sphinx", "rst.linker"] -testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] - -[[package]] -name = "importlib-resources" -version = "5.2.2" -description = "Read resources from Python packages" -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +perf = ["ipython"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] [[package]] name = "iniconfig" @@ -291,49 +225,35 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "isort" -version = "5.9.3" -description = "A Python utility / library to sort Python imports." -category = "dev" -optional = false -python-versions = ">=3.6.1,<4.0" - -[package.extras] -pipfile_deprecated_finder = ["pipreqs", "requirementslib"] -requirements_deprecated_finder = ["pipreqs", "pip-api"] -colors = ["colorama (>=0.4.3,<0.5.0)"] -plugins = ["setuptools"] - [[package]] name = "jeepney" -version = "0.7.1" +version = "0.8.0" description = "Low-level, pure Python DBus protocol wrapper." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.extras] -test = ["pytest", "pytest-trio", "pytest-asyncio", "testpath", "trio", "async-timeout"] +test = ["pytest", "pytest-trio", "pytest-asyncio (>=0.17)", "testpath", "trio", "async-timeout"] trio = ["trio", "async-generator"] [[package]] name = "keyring" -version = "22.3.0" +version = "23.5.0" description = "Store and access your passwords safely." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] -importlib-metadata = {version = ">=1", markers = "python_version < \"3.8\""} +importlib-metadata = ">=3.6" jeepney = {version = ">=0.4.2", markers = "sys_platform == \"linux\""} pywin32-ctypes = {version = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1", markers = "sys_platform == \"win32\""} SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] [[package]] name = "lockfile" @@ -345,20 +265,12 @@ python-versions = "*" [[package]] name = "msgpack" -version = "1.0.2" +version = "1.0.3" description = "MessagePack (de)serializer." category = "main" optional = false python-versions = "*" -[[package]] -name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." -category = "dev" -optional = false -python-versions = "*" - [[package]] name = "nodeenv" version = "1.6.0" @@ -378,14 +290,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.dependencies] pyparsing = ">=2.0.2" -[[package]] -name = "pathspec" -version = "0.9.0" -description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - [[package]] name = "pexpect" version = "4.8.0" @@ -399,22 +303,22 @@ ptyprocess = ">=0.5" [[package]] name = "pkginfo" -version = "1.7.1" +version = "1.8.2" description = "Query metadatdata from sdists / bdists / installed packages." category = "main" optional = false python-versions = "*" [package.extras] -testing = ["nose", "coverage"] +testing = ["coverage", "nose"] [[package]] name = "platformdirs" -version = "2.3.0" +version = "2.5.1" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" +category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.extras] docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] @@ -437,57 +341,62 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "poetry" -version = "1.2.0a2" +version = "1.2.0-beta.2.dev0" description = "Python dependency management and packaging made easy." category = "main" optional = false -python-versions = ">=3.6,<4.0" +python-versions = "^3.7" +develop = false [package.dependencies] -cachecontrol = {version = ">=0.12.4,<0.13.0", extras = ["filecache"]} -cachy = ">=0.3.0,<0.4.0" -cleo = ">=1.0.0a4,<2.0.0" -crashtest = ">=0.3.0,<0.4.0" -dataclasses = {version = ">=0.8,<0.9", markers = "python_version >= \"3.6\" and python_version < \"3.7\""} -entrypoints = ">=0.3,<0.4" -html5lib = ">=1.0,<2.0" -importlib-metadata = {version = ">=1.6.0,<2.0.0", markers = "python_version < \"3.8\""} +cachecontrol = {version = "^0.12.9", extras = ["filecache"]} +cachy = "^0.3.0" +cleo = "^1.0.0a4" +crashtest = "^0.3.0" +entrypoints = "^0.3" +html5lib = "^1.0" +importlib-metadata = {version = ">=1.6.0", markers = "python_version < \"3.8\""} keyring = ">=21.2.0" -packaging = ">=20.4,<21.0" -pexpect = ">=4.7.0,<5.0.0" -pkginfo = ">=1.5,<2.0" -poetry-core = ">=1.1.0a6,<2.0.0" -requests = ">=2.18,<3.0" -requests-toolbelt = ">=0.9.1,<0.10.0" -shellingham = ">=1.1,<2.0" +packaging = "^20.4" +pexpect = "^4.7.0" +pkginfo = "^1.5" +poetry-core = "^1.1.0a7" +requests = "^2.18" +requests-toolbelt = "^0.9.1" +shellingham = "^1.1" tomlkit = ">=0.7.0,<1.0.0" -virtualenv = ">=20.4.3,<20.4.5" +urllib3 = "^1.26.0" +virtualenv = "(>=20.4.3,<20.4.5 || >=20.4.7)" + +[package.source] +type = "git" +url = "https://github.com/abn/poetry.git" +reference = "use-export-plugin" +resolved_reference = "c5f74f605f0eecd5aedcfb75d06e5a7230ab1b16" [[package]] name = "poetry-core" -version = "1.1.0a6" +version = "1.1.0a7" description = "Poetry PEP 517 Build Backend" category = "main" optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.7,<4.0" [package.dependencies] -dataclasses = {version = ">=0.8", markers = "python_version >= \"3.6\" and python_version < \"3.7\""} importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""} [[package]] name = "pre-commit" -version = "2.15.0" +version = "2.18.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.7" [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} -importlib-resources = {version = "*", markers = "python_version < \"3.7\""} nodeenv = ">=0.11.1" pyyaml = ">=5.1" toml = "*" @@ -503,15 +412,15 @@ python-versions = "*" [[package]] name = "py" -version = "1.10.0" +version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "pycparser" -version = "2.20" +version = "2.21" description = "C parser in Python" category = "main" optional = false @@ -527,19 +436,22 @@ python-versions = "*" [[package]] name = "pyparsing" -version = "2.4.7" +version = "3.0.7" description = "Python parsing module" category = "main" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = ">=3.6" + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "6.2.5" +version = "7.1.1" description = "pytest: simple powerful testing with Python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} @@ -550,18 +462,18 @@ iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" py = ">=1.8.2" -toml = "*" +tomli = ">=1.0.0" [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] [[package]] name = "pytest-mock" -version = "3.6.1" +version = "3.7.0" description = "Thin-wrapper around the mock package for easier use with pytest" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] pytest = ">=5.0" @@ -579,23 +491,15 @@ python-versions = "*" [[package]] name = "pyyaml" -version = "5.4.1" +version = "6.0" description = "YAML parser and emitter for Python" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" - -[[package]] -name = "regex" -version = "2021.8.28" -description = "Alternative regular expression module, to replace re." -category = "dev" -optional = false -python-versions = "*" +python-versions = ">=3.6" [[package]] name = "requests" -version = "2.26.0" +version = "2.27.1" description = "Python HTTP for Humans." category = "main" optional = false @@ -660,68 +564,59 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "tomli" -version = "1.2.1" +version = "2.0.1" description = "A lil' TOML parser" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "tomlkit" -version = "0.7.2" +version = "0.10.1" description = "Style preserving TOML library" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "typed-ast" -version = "1.4.3" -description = "a fork of Python 2 and 3 ast modules with type comment support" -category = "dev" -optional = false -python-versions = "*" +python-versions = ">=3.6,<4.0" [[package]] name = "typing-extensions" -version = "3.10.0.2" -description = "Backported and Experimental Type Hints for Python 3.5+" -category = "dev" +version = "4.1.1" +description = "Backported and Experimental Type Hints for Python 3.6+" +category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [[package]] name = "urllib3" -version = "1.26.6" +version = "1.26.9" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" [package.extras] -brotli = ["brotlipy (>=0.6.0)"] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.4.4" +version = "20.14.0" description = "Virtual Python Environment builder" category = "main" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] -appdirs = ">=1.4.3,<2" distlib = ">=0.3.1,<1" -filelock = ">=3.0.0,<4" +filelock = ">=3.2,<4" importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} -importlib-resources = {version = ">=1.0", markers = "python_version < \"3.7\""} +platformdirs = ">=2,<3" six = ">=1.9.0,<2" [package.extras] -docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"] -testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)", "xonsh (>=0.9.16)"] +docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] +testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] [[package]] name = "webencodings" @@ -733,113 +628,106 @@ python-versions = "*" [[package]] name = "zipp" -version = "3.5.0" +version = "3.8.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [metadata] lock-version = "1.1" -python-versions = "^3.6" -content-hash = "e46d0fb8162693205bb056c3fd73a8bd49d4320de9d250ca04cec5a9872ea54d" +python-versions = "^3.7" +content-hash = "90f3e97cd2d184279fb3e5c0ebf6cba349fbf615158e98817e27ad1925e895a2" [metadata.files] -appdirs = [ - {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, - {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, -] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, ] attrs = [ - {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, - {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, -] -black = [ - {file = "black-21.8b0-py3-none-any.whl", hash = "sha256:2a0f9a8c2b2a60dbcf1ccb058842fb22bdbbcb2f32c6cc02d9578f90b92ce8b7"}, - {file = "black-21.8b0.tar.gz", hash = "sha256:570608d28aa3af1792b98c4a337dbac6367877b47b12b88ab42095cfc1a627c2"}, + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, ] cachecontrol = [ - {file = "CacheControl-0.12.6-py2.py3-none-any.whl", hash = "sha256:10d056fa27f8563a271b345207402a6dcce8efab7e5b377e270329c62471b10d"}, - {file = "CacheControl-0.12.6.tar.gz", hash = "sha256:be9aa45477a134aee56c8fac518627e1154df063e85f67d4f83ce0ccc23688e8"}, + {file = "CacheControl-0.12.10-py2.py3-none-any.whl", hash = "sha256:b0d43d8f71948ef5ebdee5fe236b86c6ffc7799370453dccb0e894c20dfa487c"}, + {file = "CacheControl-0.12.10.tar.gz", hash = "sha256:d8aca75b82eec92d84b5d6eb8c8f66ea16f09d2adb09dbca27fe2d5fc8d3732d"}, ] cachy = [ {file = "cachy-0.3.0-py2.py3-none-any.whl", hash = "sha256:338ca09c8860e76b275aff52374330efedc4d5a5e45dc1c5b539c1ead0786fe7"}, {file = "cachy-0.3.0.tar.gz", hash = "sha256:186581f4ceb42a0bbe040c407da73c14092379b1e4c0e327fdb72ae4a9b269b1"}, ] certifi = [ - {file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"}, - {file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"}, + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, ] cffi = [ - {file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"}, - {file = "cffi-1.14.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99"}, - {file = "cffi-1.14.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819"}, - {file = "cffi-1.14.6-cp27-cp27m-win32.whl", hash = "sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20"}, - {file = "cffi-1.14.6-cp27-cp27m-win_amd64.whl", hash = "sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224"}, - {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7"}, - {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33"}, - {file = "cffi-1.14.6-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534"}, - {file = "cffi-1.14.6-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a"}, - {file = "cffi-1.14.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5"}, - {file = "cffi-1.14.6-cp35-cp35m-win32.whl", hash = "sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca"}, - {file = "cffi-1.14.6-cp35-cp35m-win_amd64.whl", hash = "sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218"}, - {file = "cffi-1.14.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb"}, - {file = "cffi-1.14.6-cp36-cp36m-win32.whl", hash = "sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a"}, - {file = "cffi-1.14.6-cp36-cp36m-win_amd64.whl", hash = "sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e"}, - {file = "cffi-1.14.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762"}, - {file = "cffi-1.14.6-cp37-cp37m-win32.whl", hash = "sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771"}, - {file = "cffi-1.14.6-cp37-cp37m-win_amd64.whl", hash = "sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a"}, - {file = "cffi-1.14.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc"}, - {file = "cffi-1.14.6-cp38-cp38-win32.whl", hash = "sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548"}, - {file = "cffi-1.14.6-cp38-cp38-win_amd64.whl", hash = "sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156"}, - {file = "cffi-1.14.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87"}, - {file = "cffi-1.14.6-cp39-cp39-win32.whl", hash = "sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728"}, - {file = "cffi-1.14.6-cp39-cp39-win_amd64.whl", hash = "sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2"}, - {file = "cffi-1.14.6.tar.gz", hash = "sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd"}, + {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"}, + {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"}, + {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"}, + {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"}, + {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"}, + {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"}, + {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"}, + {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"}, + {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"}, + {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"}, + {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"}, + {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"}, + {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"}, + {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"}, + {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"}, + {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"}, + {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"}, + {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"}, + {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"}, + {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"}, + {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"}, + {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"}, + {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"}, + {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, + {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, ] cfgv = [ {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, ] charset-normalizer = [ - {file = "charset-normalizer-2.0.4.tar.gz", hash = "sha256:f23667ebe1084be45f6ae0538e4a5a865206544097e4e8bbcacf42cd02a348f3"}, - {file = "charset_normalizer-2.0.4-py3-none-any.whl", hash = "sha256:0c8911edd15d19223366a194a513099a302055a962bca2cec0f54b8b63175d8b"}, + {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, + {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, ] cleo = [ {file = "cleo-1.0.0a4-py3-none-any.whl", hash = "sha256:cdd0c3458c15ced3a9f0204b1e53a1b4bee3c56ebcb3ac54c872a56acc657a09"}, {file = "cleo-1.0.0a4.tar.gz", hash = "sha256:a103a065d031b7d936ee88a6b93086a69bd9c1b40fa2ebfe8c056285a66b481d"}, ] -click = [ - {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"}, - {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"}, -] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, @@ -849,113 +737,106 @@ crashtest = [ {file = "crashtest-0.3.1.tar.gz", hash = "sha256:42ca7b6ce88b6c7433e2ce47ea884e91ec93104a4b754998be498a8e6c3d37dd"}, ] cryptography = [ - {file = "cryptography-3.4.8-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:a00cf305f07b26c351d8d4e1af84ad7501eca8a342dedf24a7acb0e7b7406e14"}, - {file = "cryptography-3.4.8-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:f44d141b8c4ea5eb4dbc9b3ad992d45580c1d22bf5e24363f2fbf50c2d7ae8a7"}, - {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0a7dcbcd3f1913f664aca35d47c1331fce738d44ec34b7be8b9d332151b0b01e"}, - {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34dae04a0dce5730d8eb7894eab617d8a70d0c97da76b905de9efb7128ad7085"}, - {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb7bb0df6f6f583dd8e054689def236255161ebbcf62b226454ab9ec663746b"}, - {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:9965c46c674ba8cc572bc09a03f4c649292ee73e1b683adb1ce81e82e9a6a0fb"}, - {file = "cryptography-3.4.8-cp36-abi3-win32.whl", hash = "sha256:21ca464b3a4b8d8e86ba0ee5045e103a1fcfac3b39319727bc0fc58c09c6aff7"}, - {file = "cryptography-3.4.8-cp36-abi3-win_amd64.whl", hash = "sha256:3520667fda779eb788ea00080124875be18f2d8f0848ec00733c0ec3bb8219fc"}, - {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d2a6e5ef66503da51d2110edf6c403dc6b494cc0082f85db12f54e9c5d4c3ec5"}, - {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a305600e7a6b7b855cd798e00278161b681ad6e9b7eca94c721d5f588ab212af"}, - {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:3fa3a7ccf96e826affdf1a0a9432be74dc73423125c8f96a909e3835a5ef194a"}, - {file = "cryptography-3.4.8-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:d9ec0e67a14f9d1d48dd87a2531009a9b251c02ea42851c060b25c782516ff06"}, - {file = "cryptography-3.4.8-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5b0fbfae7ff7febdb74b574055c7466da334a5371f253732d7e2e7525d570498"}, - {file = "cryptography-3.4.8-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94fff993ee9bc1b2440d3b7243d488c6a3d9724cc2b09cdb297f6a886d040ef7"}, - {file = "cryptography-3.4.8-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:8695456444f277af73a4877db9fc979849cd3ee74c198d04fc0776ebc3db52b9"}, - {file = "cryptography-3.4.8-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:cd65b60cfe004790c795cc35f272e41a3df4631e2fb6b35aa7ac6ef2859d554e"}, - {file = "cryptography-3.4.8.tar.gz", hash = "sha256:94cc5ed4ceaefcbe5bf38c8fba6a21fc1d365bb8fb826ea1688e3370b2e24a1c"}, -] -dataclasses = [ - {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"}, - {file = "dataclasses-0.8.tar.gz", hash = "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97"}, + {file = "cryptography-36.0.2-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:4e2dddd38a5ba733be6a025a1475a9f45e4e41139d1321f412c6b360b19070b6"}, + {file = "cryptography-36.0.2-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:4881d09298cd0b669bb15b9cfe6166f16fc1277b4ed0d04a22f3d6430cb30f1d"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea634401ca02367c1567f012317502ef3437522e2fc44a3ea1844de028fa4b84"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7be666cc4599b415f320839e36367b273db8501127b38316f3b9f22f17a0b815"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8241cac0aae90b82d6b5c443b853723bcc66963970c67e56e71a2609dc4b5eaf"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b2d54e787a884ffc6e187262823b6feb06c338084bbe80d45166a1cb1c6c5bf"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:c2c5250ff0d36fd58550252f54915776940e4e866f38f3a7866d92b32a654b86"}, + {file = "cryptography-36.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ec6597aa85ce03f3e507566b8bcdf9da2227ec86c4266bd5e6ab4d9e0cc8dab2"}, + {file = "cryptography-36.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ca9f686517ec2c4a4ce930207f75c00bf03d94e5063cbc00a1dc42531511b7eb"}, + {file = "cryptography-36.0.2-cp36-abi3-win32.whl", hash = "sha256:f64b232348ee82f13aac22856515ce0195837f6968aeaa94a3d0353ea2ec06a6"}, + {file = "cryptography-36.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:53e0285b49fd0ab6e604f4c5d9c5ddd98de77018542e88366923f152dbeb3c29"}, + {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:32db5cc49c73f39aac27574522cecd0a4bb7384e71198bc65a0d23f901e89bb7"}, + {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b3d199647468d410994dbeb8cec5816fb74feb9368aedf300af709ef507e3e"}, + {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:da73d095f8590ad437cd5e9faf6628a218aa7c387e1fdf67b888b47ba56a17f0"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:0a3bf09bb0b7a2c93ce7b98cb107e9170a90c51a0162a20af1c61c765b90e60b"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8897b7b7ec077c819187a123174b645eb680c13df68354ed99f9b40a50898f77"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82740818f2f240a5da8dfb8943b360e4f24022b093207160c77cadade47d7c85"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:1f64a62b3b75e4005df19d3b5235abd43fa6358d5516cfc43d87aeba8d08dd51"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e167b6b710c7f7bc54e67ef593f8731e1f45aa35f8a8a7b72d6e42ec76afd4b3"}, + {file = "cryptography-36.0.2.tar.gz", hash = "sha256:70f8f4f7bb2ac9f340655cbac89d68c527af5bb4387522a8413e841e3e6628c9"}, ] distlib = [ - {file = "distlib-0.3.2-py2.py3-none-any.whl", hash = "sha256:23e223426b28491b1ced97dc3bbe183027419dfc7982b4fa2f05d5f3ff10711c"}, - {file = "distlib-0.3.2.zip", hash = "sha256:106fef6dc37dd8c0e2c0a60d3fca3e77460a48907f335fa28420463a6f799736"}, + {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, + {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, ] entrypoints = [ {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, ] filelock = [ - {file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"}, - {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, + {file = "filelock-3.6.0-py3-none-any.whl", hash = "sha256:f8314284bfffbdcfa0ff3d7992b023d4c628ced6feb957351d4c48d059f56bc0"}, + {file = "filelock-3.6.0.tar.gz", hash = "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85"}, ] html5lib = [ {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, ] identify = [ - {file = "identify-2.2.13-py2.py3-none-any.whl", hash = "sha256:7199679b5be13a6b40e6e19ea473e789b11b4e3b60986499b1f589ffb03c217c"}, - {file = "identify-2.2.13.tar.gz", hash = "sha256:7bc6e829392bd017236531963d2d937d66fc27cadc643ac0aba2ce9f26157c79"}, + {file = "identify-2.4.12-py2.py3-none-any.whl", hash = "sha256:5f06b14366bd1facb88b00540a1de05b69b310cbc2654db3c7e07fa3a4339323"}, + {file = "identify-2.4.12.tar.gz", hash = "sha256:3f3244a559290e7d3deb9e9adc7b33594c1bc85a9dd82e0f1be519bf12a1ec17"}, ] idna = [ - {file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"}, - {file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"}, + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] importlib-metadata = [ - {file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"}, - {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"}, -] -importlib-resources = [ - {file = "importlib_resources-5.2.2-py3-none-any.whl", hash = "sha256:2480d8e07d1890056cb53c96e3de44fead9c62f2ba949b0f2e4c4345f4afa977"}, - {file = "importlib_resources-5.2.2.tar.gz", hash = "sha256:a65882a4d0fe5fbf702273456ba2ce74fe44892c25e42e057aca526b702a6d4b"}, + {file = "importlib_metadata-4.11.3-py3-none-any.whl", hash = "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6"}, + {file = "importlib_metadata-4.11.3.tar.gz", hash = "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] -isort = [ - {file = "isort-5.9.3-py3-none-any.whl", hash = "sha256:e17d6e2b81095c9db0a03a8025a957f334d6ea30b26f9ec70805411e5c7c81f2"}, - {file = "isort-5.9.3.tar.gz", hash = "sha256:9c2ea1e62d871267b78307fe511c0838ba0da28698c5732d54e2790bf3ba9899"}, -] jeepney = [ - {file = "jeepney-0.7.1-py3-none-any.whl", hash = "sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac"}, - {file = "jeepney-0.7.1.tar.gz", hash = "sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f"}, + {file = "jeepney-0.8.0-py3-none-any.whl", hash = "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755"}, + {file = "jeepney-0.8.0.tar.gz", hash = "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806"}, ] keyring = [ - {file = "keyring-22.3.0-py3-none-any.whl", hash = "sha256:2bc8363ebdd63886126a012057a85c8cb6e143877afa02619ac7dbc9f38a207b"}, - {file = "keyring-22.3.0.tar.gz", hash = "sha256:16927a444b2c73f983520a48dec79ddab49fe76429ea05b8d528d778c8339522"}, + {file = "keyring-23.5.0-py3-none-any.whl", hash = "sha256:b0d28928ac3ec8e42ef4cc227822647a19f1d544f21f96457965dc01cf555261"}, + {file = "keyring-23.5.0.tar.gz", hash = "sha256:9012508e141a80bd1c0b6778d5c610dd9f8c464d75ac6774248500503f972fb9"}, ] lockfile = [ {file = "lockfile-0.12.2-py2.py3-none-any.whl", hash = "sha256:6c3cb24f344923d30b2785d5ad75182c8ea7ac1b6171b08657258ec7429d50fa"}, {file = "lockfile-0.12.2.tar.gz", hash = "sha256:6aed02de03cba24efabcd600b30540140634fc06cfa603822d508d5361e9f799"}, ] msgpack = [ - {file = "msgpack-1.0.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:b6d9e2dae081aa35c44af9c4298de4ee72991305503442a5c74656d82b581fe9"}, - {file = "msgpack-1.0.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a99b144475230982aee16b3d249170f1cccebf27fb0a08e9f603b69637a62192"}, - {file = "msgpack-1.0.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1026dcc10537d27dd2d26c327e552f05ce148977e9d7b9f1718748281b38c841"}, - {file = "msgpack-1.0.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:fe07bc6735d08e492a327f496b7850e98cb4d112c56df69b0c844dbebcbb47f6"}, - {file = "msgpack-1.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:9ea52fff0473f9f3000987f313310208c879493491ef3ccf66268eff8d5a0326"}, - {file = "msgpack-1.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:26a1759f1a88df5f1d0b393eb582ec022326994e311ba9c5818adc5374736439"}, - {file = "msgpack-1.0.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:497d2c12426adcd27ab83144057a705efb6acc7e85957a51d43cdcf7f258900f"}, - {file = "msgpack-1.0.2-cp36-cp36m-win32.whl", hash = "sha256:e89ec55871ed5473a041c0495b7b4e6099f6263438e0bd04ccd8418f92d5d7f2"}, - {file = "msgpack-1.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a4355d2193106c7aa77c98fc955252a737d8550320ecdb2e9ac701e15e2943bc"}, - {file = "msgpack-1.0.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:d6c64601af8f3893d17ec233237030e3110f11b8a962cb66720bf70c0141aa54"}, - {file = "msgpack-1.0.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f484cd2dca68502de3704f056fa9b318c94b1539ed17a4c784266df5d6978c87"}, - {file = "msgpack-1.0.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f3e6aaf217ac1c7ce1563cf52a2f4f5d5b1f64e8729d794165db71da57257f0c"}, - {file = "msgpack-1.0.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:8521e5be9e3b93d4d5e07cb80b7e32353264d143c1f072309e1863174c6aadb1"}, - {file = "msgpack-1.0.2-cp37-cp37m-win32.whl", hash = "sha256:31c17bbf2ae5e29e48d794c693b7ca7a0c73bd4280976d408c53df421e838d2a"}, - {file = "msgpack-1.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8ffb24a3b7518e843cd83538cf859e026d24ec41ac5721c18ed0c55101f9775b"}, - {file = "msgpack-1.0.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:b28c0876cce1466d7c2195d7658cf50e4730667196e2f1355c4209444717ee06"}, - {file = "msgpack-1.0.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:87869ba567fe371c4555d2e11e4948778ab6b59d6cc9d8460d543e4cfbbddd1c"}, - {file = "msgpack-1.0.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b55f7db883530b74c857e50e149126b91bb75d35c08b28db12dcb0346f15e46e"}, - {file = "msgpack-1.0.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:ac25f3e0513f6673e8b405c3a80500eb7be1cf8f57584be524c4fa78fe8e0c83"}, - {file = "msgpack-1.0.2-cp38-cp38-win32.whl", hash = "sha256:0cb94ee48675a45d3b86e61d13c1e6f1696f0183f0715544976356ff86f741d9"}, - {file = "msgpack-1.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:e36a812ef4705a291cdb4a2fd352f013134f26c6ff63477f20235138d1d21009"}, - {file = "msgpack-1.0.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2a5866bdc88d77f6e1370f82f2371c9bc6fc92fe898fa2dec0c5d4f5435a2694"}, - {file = "msgpack-1.0.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:92be4b12de4806d3c36810b0fe2aeedd8d493db39e2eb90742b9c09299eb5759"}, - {file = "msgpack-1.0.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:de6bd7990a2c2dabe926b7e62a92886ccbf809425c347ae7de277067f97c2887"}, - {file = "msgpack-1.0.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5a9ee2540c78659a1dd0b110f73773533ee3108d4e1219b5a15a8d635b7aca0e"}, - {file = "msgpack-1.0.2-cp39-cp39-win32.whl", hash = "sha256:c747c0cc08bd6d72a586310bda6ea72eeb28e7505990f342552315b229a19b33"}, - {file = "msgpack-1.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:d8167b84af26654c1124857d71650404336f4eb5cc06900667a493fc619ddd9f"}, - {file = "msgpack-1.0.2.tar.gz", hash = "sha256:fae04496f5bc150eefad4e9571d1a76c55d021325dcd484ce45065ebbdd00984"}, -] -mypy-extensions = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, + {file = "msgpack-1.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:96acc674bb9c9be63fa8b6dabc3248fdc575c4adc005c440ad02f87ca7edd079"}, + {file = "msgpack-1.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2c3ca57c96c8e69c1a0d2926a6acf2d9a522b41dc4253a8945c4c6cd4981a4e3"}, + {file = "msgpack-1.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0a792c091bac433dfe0a70ac17fc2087d4595ab835b47b89defc8bbabcf5c73"}, + {file = "msgpack-1.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c58cdec1cb5fcea8c2f1771d7b5fec79307d056874f746690bd2bdd609ab147"}, + {file = "msgpack-1.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f97c0f35b3b096a330bb4a1a9247d0bd7e1f3a2eba7ab69795501504b1c2c39"}, + {file = "msgpack-1.0.3-cp310-cp310-win32.whl", hash = "sha256:36a64a10b16c2ab31dcd5f32d9787ed41fe68ab23dd66957ca2826c7f10d0b85"}, + {file = "msgpack-1.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c1ba333b4024c17c7591f0f372e2daa3c31db495a9b2af3cf664aef3c14354f7"}, + {file = "msgpack-1.0.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c2140cf7a3ec475ef0938edb6eb363fa704159e0bf71dde15d953bacc1cf9d7d"}, + {file = "msgpack-1.0.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f4c22717c74d44bcd7af353024ce71c6b55346dad5e2cc1ddc17ce8c4507c6b"}, + {file = "msgpack-1.0.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d733a15ade190540c703de209ffbc42a3367600421b62ac0c09fde594da6ec"}, + {file = "msgpack-1.0.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7e03b06f2982aa98d4ddd082a210c3db200471da523f9ac197f2828e80e7770"}, + {file = "msgpack-1.0.3-cp36-cp36m-win32.whl", hash = "sha256:3d875631ecab42f65f9dce6f55ce6d736696ced240f2634633188de2f5f21af9"}, + {file = "msgpack-1.0.3-cp36-cp36m-win_amd64.whl", hash = "sha256:40fb89b4625d12d6027a19f4df18a4de5c64f6f3314325049f219683e07e678a"}, + {file = "msgpack-1.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6eef0cf8db3857b2b556213d97dd82de76e28a6524853a9beb3264983391dc1a"}, + {file = "msgpack-1.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d8c332f53ffff01953ad25131272506500b14750c1d0ce8614b17d098252fbc"}, + {file = "msgpack-1.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c0903bd93cbd34653dd63bbfcb99d7539c372795201f39d16fdfde4418de43a"}, + {file = "msgpack-1.0.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bf1e6bfed4860d72106f4e0a1ab519546982b45689937b40257cfd820650b920"}, + {file = "msgpack-1.0.3-cp37-cp37m-win32.whl", hash = "sha256:d02cea2252abc3756b2ac31f781f7a98e89ff9759b2e7450a1c7a0d13302ff50"}, + {file = "msgpack-1.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2f30dd0dc4dfe6231ad253b6f9f7128ac3202ae49edd3f10d311adc358772dba"}, + {file = "msgpack-1.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f201d34dc89342fabb2a10ed7c9a9aaaed9b7af0f16a5923f1ae562b31258dea"}, + {file = "msgpack-1.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bb87f23ae7d14b7b3c21009c4b1705ec107cb21ee71975992f6aca571fb4a42a"}, + {file = "msgpack-1.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a3a5c4b16e9d0edb823fe54b59b5660cc8d4782d7bf2c214cb4b91a1940a8ef"}, + {file = "msgpack-1.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f74da1e5fcf20ade12c6bf1baa17a2dc3604958922de8dc83cbe3eff22e8b611"}, + {file = "msgpack-1.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:73a80bd6eb6bcb338c1ec0da273f87420829c266379c8c82fa14c23fb586cfa1"}, + {file = "msgpack-1.0.3-cp38-cp38-win32.whl", hash = "sha256:9fce00156e79af37bb6db4e7587b30d11e7ac6a02cb5bac387f023808cd7d7f4"}, + {file = "msgpack-1.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:9b6f2d714c506e79cbead331de9aae6837c8dd36190d02da74cb409b36162e8a"}, + {file = "msgpack-1.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:89908aea5f46ee1474cc37fbc146677f8529ac99201bc2faf4ef8edc023c2bf3"}, + {file = "msgpack-1.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:973ad69fd7e31159eae8f580f3f707b718b61141838321c6fa4d891c4a2cca52"}, + {file = "msgpack-1.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da24375ab4c50e5b7486c115a3198d207954fe10aaa5708f7b65105df09109b2"}, + {file = "msgpack-1.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a598d0685e4ae07a0672b59792d2cc767d09d7a7f39fd9bd37ff84e060b1a996"}, + {file = "msgpack-1.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4c309a68cb5d6bbd0c50d5c71a25ae81f268c2dc675c6f4ea8ab2feec2ac4e2"}, + {file = "msgpack-1.0.3-cp39-cp39-win32.whl", hash = "sha256:494471d65b25a8751d19c83f1a482fd411d7ca7a3b9e17d25980a74075ba0e88"}, + {file = "msgpack-1.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:f01b26c2290cbd74316990ba84a14ac3d599af9cebefc543d241a66e785cf17d"}, + {file = "msgpack-1.0.3.tar.gz", hash = "sha256:51fdc7fb93615286428ee7758cecc2f374d5ff363bdd884c7ea622a7a327a81e"}, ] nodeenv = [ {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, @@ -965,134 +846,102 @@ packaging = [ {file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"}, {file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"}, ] -pathspec = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, -] pexpect = [ {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, ] -pkginfo = [] +pkginfo = [ + {file = "pkginfo-1.8.2-py2.py3-none-any.whl", hash = "sha256:c24c487c6a7f72c66e816ab1796b96ac6c3d14d49338293d2141664330b55ffc"}, + {file = "pkginfo-1.8.2.tar.gz", hash = "sha256:542e0d0b6750e2e21c20179803e40ab50598d8066d51097a0e382cba9eb02bff"}, +] platformdirs = [ - {file = "platformdirs-2.3.0-py3-none-any.whl", hash = "sha256:8003ac87717ae2c7ee1ea5a84a1a61e87f3fbd16eb5aadba194ea30a9019f648"}, - {file = "platformdirs-2.3.0.tar.gz", hash = "sha256:15b056538719b1c94bdaccb29e5f81879c7f7f0f4a153f46086d155dffcd4f0f"}, + {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, + {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, ] pluggy = [ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] -poetry = [ - {file = "poetry-1.2.0a2-py3-none-any.whl", hash = "sha256:475fe6884a0a2ec97eee9daca80c37210aee4cd78b6d9ca8e800fad8d3828624"}, - {file = "poetry-1.2.0a2.tar.gz", hash = "sha256:4bad54dd1b40fd7b7efe90f05288ebab3d55b091cb682c847eac1d24ff1d1e31"}, -] +poetry = [] poetry-core = [ - {file = "poetry-core-1.1.0a6.tar.gz", hash = "sha256:e22c8897216216f6344b3d57167a8cd5485a1403934817d7efaf7fb8f6bcffc9"}, - {file = "poetry_core-1.1.0a6-py3-none-any.whl", hash = "sha256:4093226d89e1b79f16c917fba766461c01b184d3184d7cad4b7be8426c0cb4be"}, + {file = "poetry-core-1.1.0a7.tar.gz", hash = "sha256:4622ae680842ac9b1b9c3b0e8dc467c2e291d1a5c434b6bd413907a2e5571d92"}, + {file = "poetry_core-1.1.0a7-py3-none-any.whl", hash = "sha256:724e8b5368f270461e622396305d0c2e760ec9d4c14d072e6b944da9384c67de"}, ] pre-commit = [ - {file = "pre_commit-2.15.0-py2.py3-none-any.whl", hash = "sha256:a4ed01000afcb484d9eb8d504272e642c4c4099bbad3a6b27e519bd6a3e928a6"}, - {file = "pre_commit-2.15.0.tar.gz", hash = "sha256:3c25add78dbdfb6a28a651780d5c311ac40dd17f160eb3954a0c59da40a505a7"}, + {file = "pre_commit-2.18.1-py2.py3-none-any.whl", hash = "sha256:02226e69564ebca1a070bd1f046af866aa1c318dbc430027c50ab832ed2b73f2"}, + {file = "pre_commit-2.18.1.tar.gz", hash = "sha256:5d445ee1fa8738d506881c5d84f83c62bb5be6b2838e32207433647e8e5ebe10"}, ] ptyprocess = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, ] py = [ - {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, - {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] pycparser = [ - {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, - {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] pylev = [ {file = "pylev-1.4.0-py2.py3-none-any.whl", hash = "sha256:7b2e2aa7b00e05bb3f7650eb506fc89f474f70493271a35c242d9a92188ad3dd"}, {file = "pylev-1.4.0.tar.gz", hash = "sha256:9e77e941042ad3a4cc305dcdf2b2dec1aec2fbe3dd9015d2698ad02b173006d1"}, ] pyparsing = [ - {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, - {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, + {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, + {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, ] pytest = [ - {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, - {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, + {file = "pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea"}, + {file = "pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63"}, ] pytest-mock = [ - {file = "pytest-mock-3.6.1.tar.gz", hash = "sha256:40217a058c52a63f1042f0784f62009e976ba824c418cced42e88d5f40ab0e62"}, - {file = "pytest_mock-3.6.1-py3-none-any.whl", hash = "sha256:30c2f2cc9759e76eee674b81ea28c9f0b94f8f0445a1b87762cadf774f0df7e3"}, + {file = "pytest-mock-3.7.0.tar.gz", hash = "sha256:5112bd92cc9f186ee96e1a92efc84969ea494939c3aead39c50f421c4cc69534"}, + {file = "pytest_mock-3.7.0-py3-none-any.whl", hash = "sha256:6cff27cec936bf81dc5ee87f07132b807bcda51106b5ec4b90a04331cba76231"}, ] pywin32-ctypes = [ {file = "pywin32-ctypes-0.2.0.tar.gz", hash = "sha256:24ffc3b341d457d48e8922352130cf2644024a4ff09762a2261fd34c36ee5942"}, {file = "pywin32_ctypes-0.2.0-py2.py3-none-any.whl", hash = "sha256:9dc2d991b3479cc2df15930958b674a48a227d5361d413827a4cfd0b5876fc98"}, ] pyyaml = [ - {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, - {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, - {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, - {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, - {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, - {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, - {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, - {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, - {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, - {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, - {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, -] -regex = [ - {file = "regex-2021.8.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9d05ad5367c90814099000442b2125535e9d77581855b9bee8780f1b41f2b1a2"}, - {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3bf1bc02bc421047bfec3343729c4bbbea42605bcfd6d6bfe2c07ade8b12d2a"}, - {file = "regex-2021.8.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f6a808044faae658f546dd5f525e921de9fa409de7a5570865467f03a626fc0"}, - {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a617593aeacc7a691cc4af4a4410031654f2909053bd8c8e7db837f179a630eb"}, - {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79aef6b5cd41feff359acaf98e040844613ff5298d0d19c455b3d9ae0bc8c35a"}, - {file = "regex-2021.8.28-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0fc1f8f06977c2d4f5e3d3f0d4a08089be783973fc6b6e278bde01f0544ff308"}, - {file = "regex-2021.8.28-cp310-cp310-win32.whl", hash = "sha256:6eebf512aa90751d5ef6a7c2ac9d60113f32e86e5687326a50d7686e309f66ed"}, - {file = "regex-2021.8.28-cp310-cp310-win_amd64.whl", hash = "sha256:ac88856a8cbccfc14f1b2d0b829af354cc1743cb375e7f04251ae73b2af6adf8"}, - {file = "regex-2021.8.28-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c206587c83e795d417ed3adc8453a791f6d36b67c81416676cad053b4104152c"}, - {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8690ed94481f219a7a967c118abaf71ccc440f69acd583cab721b90eeedb77c"}, - {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:328a1fad67445550b982caa2a2a850da5989fd6595e858f02d04636e7f8b0b13"}, - {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c7cb4c512d2d3b0870e00fbbac2f291d4b4bf2634d59a31176a87afe2777c6f0"}, - {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66256b6391c057305e5ae9209941ef63c33a476b73772ca967d4a2df70520ec1"}, - {file = "regex-2021.8.28-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8e44769068d33e0ea6ccdf4b84d80c5afffe5207aa4d1881a629cf0ef3ec398f"}, - {file = "regex-2021.8.28-cp36-cp36m-win32.whl", hash = "sha256:08d74bfaa4c7731b8dac0a992c63673a2782758f7cfad34cf9c1b9184f911354"}, - {file = "regex-2021.8.28-cp36-cp36m-win_amd64.whl", hash = "sha256:abb48494d88e8a82601af905143e0de838c776c1241d92021e9256d5515b3645"}, - {file = "regex-2021.8.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4c220a1fe0d2c622493b0a1fd48f8f991998fb447d3cd368033a4b86cf1127a"}, - {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4a332404baa6665b54e5d283b4262f41f2103c255897084ec8f5487ce7b9e8e"}, - {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c61dcc1cf9fd165127a2853e2c31eb4fb961a4f26b394ac9fe5669c7a6592892"}, - {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ee329d0387b5b41a5dddbb6243a21cb7896587a651bebb957e2d2bb8b63c0791"}, - {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60667673ff9c249709160529ab39667d1ae9fd38634e006bec95611f632e759"}, - {file = "regex-2021.8.28-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b844fb09bd9936ed158ff9df0ab601e2045b316b17aa8b931857365ea8586906"}, - {file = "regex-2021.8.28-cp37-cp37m-win32.whl", hash = "sha256:4cde065ab33bcaab774d84096fae266d9301d1a2f5519d7bd58fc55274afbf7a"}, - {file = "regex-2021.8.28-cp37-cp37m-win_amd64.whl", hash = "sha256:1413b5022ed6ac0d504ba425ef02549a57d0f4276de58e3ab7e82437892704fc"}, - {file = "regex-2021.8.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ed4b50355b066796dacdd1cf538f2ce57275d001838f9b132fab80b75e8c84dd"}, - {file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28fc475f560d8f67cc8767b94db4c9440210f6958495aeae70fac8faec631797"}, - {file = "regex-2021.8.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdc178caebd0f338d57ae445ef8e9b737ddf8fbc3ea187603f65aec5b041248f"}, - {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:999ad08220467b6ad4bd3dd34e65329dd5d0df9b31e47106105e407954965256"}, - {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:808ee5834e06f57978da3e003ad9d6292de69d2bf6263662a1a8ae30788e080b"}, - {file = "regex-2021.8.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d5111d4c843d80202e62b4fdbb4920db1dcee4f9366d6b03294f45ed7b18b42e"}, - {file = "regex-2021.8.28-cp38-cp38-win32.whl", hash = "sha256:473858730ef6d6ff7f7d5f19452184cd0caa062a20047f6d6f3e135a4648865d"}, - {file = "regex-2021.8.28-cp38-cp38-win_amd64.whl", hash = "sha256:31a99a4796bf5aefc8351e98507b09e1b09115574f7c9dbb9cf2111f7220d2e2"}, - {file = "regex-2021.8.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:04f6b9749e335bb0d2f68c707f23bb1773c3fb6ecd10edf0f04df12a8920d468"}, - {file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b006628fe43aa69259ec04ca258d88ed19b64791693df59c422b607b6ece8bb"}, - {file = "regex-2021.8.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:121f4b3185feaade3f85f70294aef3f777199e9b5c0c0245c774ae884b110a2d"}, - {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a577a21de2ef8059b58f79ff76a4da81c45a75fe0bfb09bc8b7bb4293fa18983"}, - {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1743345e30917e8c574f273f51679c294effba6ad372db1967852f12c76759d8"}, - {file = "regex-2021.8.28-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e1e8406b895aba6caa63d9fd1b6b1700d7e4825f78ccb1e5260551d168db38ed"}, - {file = "regex-2021.8.28-cp39-cp39-win32.whl", hash = "sha256:ed283ab3a01d8b53de3a05bfdf4473ae24e43caee7dcb5584e86f3f3e5ab4374"}, - {file = "regex-2021.8.28-cp39-cp39-win_amd64.whl", hash = "sha256:610b690b406653c84b7cb6091facb3033500ee81089867ee7d59e675f9ca2b73"}, - {file = "regex-2021.8.28.tar.gz", hash = "sha256:f585cbbeecb35f35609edccb95efd95a3e35824cd7752b586503f7e6087303f1"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, +] +requests = [ + {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, + {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, ] -requests = [] requests-toolbelt = [ {file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"}, {file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"}, @@ -1114,63 +963,30 @@ toml = [ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] tomli = [ - {file = "tomli-1.2.1-py3-none-any.whl", hash = "sha256:8dd0e9524d6f386271a36b41dbf6c57d8e32fd96fd22b6584679dc569d20899f"}, - {file = "tomli-1.2.1.tar.gz", hash = "sha256:a5b75cb6f3968abb47af1b40c1819dc519ea82bcc065776a866e8d74c5ca9442"}, + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] tomlkit = [ - {file = "tomlkit-0.7.2-py2.py3-none-any.whl", hash = "sha256:173ad840fa5d2aac140528ca1933c29791b79a374a0861a80347f42ec9328117"}, - {file = "tomlkit-0.7.2.tar.gz", hash = "sha256:d7a454f319a7e9bd2e249f239168729327e4dd2d27b17dc68be264ad1ce36754"}, -] -typed-ast = [ - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6"}, - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075"}, - {file = "typed_ast-1.4.3-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528"}, - {file = "typed_ast-1.4.3-cp35-cp35m-win32.whl", hash = "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428"}, - {file = "typed_ast-1.4.3-cp35-cp35m-win_amd64.whl", hash = "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3"}, - {file = "typed_ast-1.4.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace"}, - {file = "typed_ast-1.4.3-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f"}, - {file = "typed_ast-1.4.3-cp36-cp36m-win32.whl", hash = "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363"}, - {file = "typed_ast-1.4.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7"}, - {file = "typed_ast-1.4.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04"}, - {file = "typed_ast-1.4.3-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899"}, - {file = "typed_ast-1.4.3-cp37-cp37m-win32.whl", hash = "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c"}, - {file = "typed_ast-1.4.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805"}, - {file = "typed_ast-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41"}, - {file = "typed_ast-1.4.3-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39"}, - {file = "typed_ast-1.4.3-cp38-cp38-win32.whl", hash = "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927"}, - {file = "typed_ast-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40"}, - {file = "typed_ast-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0"}, - {file = "typed_ast-1.4.3-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3"}, - {file = "typed_ast-1.4.3-cp39-cp39-win32.whl", hash = "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808"}, - {file = "typed_ast-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c"}, - {file = "typed_ast-1.4.3.tar.gz", hash = "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65"}, + {file = "tomlkit-0.10.1-py3-none-any.whl", hash = "sha256:3eba517439dcb2f84cf39f4f85fd2c3398309823a3c75ac3e73003638daf7915"}, + {file = "tomlkit-0.10.1.tar.gz", hash = "sha256:3c517894eadef53e9072d343d37e4427b8f0b6200a70b7c9a19b2ebd1f53b951"}, ] typing-extensions = [ - {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, - {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, - {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, + {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, + {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, ] urllib3 = [ - {file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"}, - {file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"}, + {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, + {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, ] virtualenv = [ - {file = "virtualenv-20.4.4-py2.py3-none-any.whl", hash = "sha256:a935126db63128861987a7d5d30e23e8ec045a73840eeccb467c148514e29535"}, - {file = "virtualenv-20.4.4.tar.gz", hash = "sha256:09c61377ef072f43568207dc8e46ddeac6bcdcaf288d49011bda0e7f4d38c4a2"}, + {file = "virtualenv-20.14.0-py2.py3-none-any.whl", hash = "sha256:1e8588f35e8b42c6ec6841a13c5e88239de1e6e4e4cedfd3916b306dc826ec66"}, + {file = "virtualenv-20.14.0.tar.gz", hash = "sha256:8e5b402037287126e81ccde9432b95a8be5b19d36584f64957060a3488c11ca8"}, ] webencodings = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] zipp = [ - {file = "zipp-3.5.0-py3-none-any.whl", hash = "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3"}, - {file = "zipp-3.5.0.tar.gz", hash = "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"}, + {file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"}, + {file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"}, ] diff --git a/pyproject.toml b/pyproject.toml index 70266c8..b2cc34a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,13 +1,13 @@ [tool.poetry] -name = "poetry-export-plugin" -version = "0.2.1" +name = "poetry-plugin-export" +version = "1.0.0-alpha.0" description = "Poetry plugin to export the dependencies to various formats" authors = ["Sébastien Eustace "] license = "MIT" readme = "README.md" packages = [ - { include = "poetry_export_plugin", from = "src" } + { include = "poetry_plugin_export", from = "src" } ] include = [ @@ -15,36 +15,21 @@ include = [ ] [tool.poetry.dependencies] -python = "^3.6" -poetry = "^1.2.0a2" +python = "^3.7" +poetry = "^1.2.0b1dev0" [tool.poetry.dev-dependencies] -black = { version = "^21.8b0", markers = "python_full_version >= '3.6.2' and python_version < '4.0' and implementation_name != 'pypy'" } -isort = { version = "^5.9.3", python = "^3.6.1" } -pre-commit = { version = "^2.6", python = "^3.6.1" } -pytest = "^6.2.3" +pre-commit = "^2.18" +pytest = "^7.1" pytest-mock = "^3.6.1" +poetry = {git = "https://github.com/abn/poetry.git", rev = "use-export-plugin"} [tool.poetry.plugins."poetry.application.plugin"] -export = "poetry_export_plugin.plugins:ExportApplicationPlugin" +export = "poetry_plugin_export.plugins:ExportApplicationPlugin" [tool.black] -line-length = 88 -include = '\.pyi?$' -exclude = ''' -/( - \.eggs - | \.git - | \.hg - | \.mypy_cache - | \.tox - | \.venv - | _build - | buck-out - | build - | dist -)/ -''' +target-version = ['py37'] +preview = true [tool.isort] profile = "black" @@ -55,6 +40,14 @@ lines_after_imports = 2 lines_between_types = 1 use_parentheses = true +[tool.mypy] +check_untyped_defs = true +ignore_missing_imports = true +show_error_codes = true +warn_redundant_casts = true +warn_unused_configs = true +warn_unused_ignores = true +files = "src" [build-system] requires = ["poetry-core"] diff --git a/src/poetry_export_plugin/__init__.py b/src/poetry_export_plugin/__init__.py deleted file mode 100644 index 3ced358..0000000 --- a/src/poetry_export_plugin/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "0.2.1" diff --git a/src/poetry_export_plugin/console/commands/__init__.py b/src/poetry_export_plugin/console/commands/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/poetry_export_plugin/plugins.py b/src/poetry_export_plugin/plugins.py deleted file mode 100644 index afb05c8..0000000 --- a/src/poetry_export_plugin/plugins.py +++ /dev/null @@ -1,43 +0,0 @@ -from importlib import import_module -from typing import TYPE_CHECKING -from typing import Callable -from typing import Type - -from poetry.plugins.application_plugin import ApplicationPlugin - - -if TYPE_CHECKING: - from poetry.console.application import Application - from poetry.console.commands.command import Command - - -def load_command(name: str) -> Callable: - def _load() -> Type["Command"]: - module = import_module( - "poetry_export_plugin.console.commands.{}".format(".".join(name.split(" "))) - ) - command_class = getattr( - module, "{}Command".format("".join(c.title() for c in name.split(" "))) - ) - - return command_class() - - return _load - - -COMMANDS = ["export"] - - -class ExportApplicationPlugin(ApplicationPlugin): - def activate(self, application: "Application"): - # Removing the existing export command to avoid an error - # until Poetry removes the export command - # and uses this plugin instead. - - # If you're checking this code out to get inspiration - # for your own plugins: DON'T DO THIS! - if "export" in application.command_loader._factories: - del application.command_loader._factories["export"] - - for command in COMMANDS: - application.command_loader.register_factory(command, load_command(command)) diff --git a/src/poetry_plugin_export/__init__.py b/src/poetry_plugin_export/__init__.py new file mode 100644 index 0000000..9b11923 --- /dev/null +++ b/src/poetry_plugin_export/__init__.py @@ -0,0 +1,6 @@ +from __future__ import annotations + +from poetry.utils._compat import metadata + + +__version__ = metadata.version("poetry-plugin-export") diff --git a/src/poetry_export_plugin/console/commands/export.py b/src/poetry_plugin_export/command.py similarity index 51% rename from src/poetry_export_plugin/console/commands/export.py rename to src/poetry_plugin_export/command.py index 1d760f0..7a62f6d 100644 --- a/src/poetry_export_plugin/console/commands/export.py +++ b/src/poetry_plugin_export/command.py @@ -1,11 +1,12 @@ -from cleo.helpers import option -from poetry.console.commands.command import Command +from __future__ import annotations -from poetry_export_plugin.exporter import Exporter +from cleo.helpers import option +from poetry.console.commands.installer_command import InstallerCommand +from poetry_plugin_export.exporter import Exporter -class ExportCommand(Command): +class ExportCommand(InstallerCommand): name = "export" description = "Exports the lock file to alternative formats." @@ -18,34 +19,18 @@ class ExportCommand(Command): default=Exporter.FORMAT_REQUIREMENTS_TXT, ), option("output", "o", "The name of the output file.", flag=False), + option("without-hashes", None, "Exclude hashes from the exported file."), option( - "without", - None, - "The dependency groups to ignore when exporting.", - flag=False, - multiple=True, - ), - option( - "with", - None, - "The optional dependency groups to include when exporting.", - flag=False, - multiple=True, - ), - option("default", None, "Only export the default dependencies."), - option( - "only", + "without-urls", None, - "The only dependency groups to include when exporting.", - flag=False, - multiple=True, + "Exclude source repository urls from the exported file.", ), option( "dev", None, "Include development dependencies. (Deprecated)", ), - option("without-hashes", None, "Exclude hashes from the exported file."), + *InstallerCommand._group_dependency_options(), option( "extras", "E", @@ -59,44 +44,8 @@ class ExportCommand(Command): def handle(self) -> None: fmt = self.option("format") - if fmt not in Exporter.ACCEPTED_FORMATS: - raise ValueError("Invalid export format: {}".format(fmt)) - - excluded_groups = [] - included_groups = [] - only_groups = [] - if self.option("dev"): - self.line_error( - "The --dev option is deprecated, " - "use the `--with dev` notation instead." - ) - self.line_error("") - included_groups.append("dev") - - excluded_groups.extend( - [ - group.strip() - for groups in self.option("without") - for group in groups.split(",") - ] - ) - included_groups.extend( - [ - group.strip() - for groups in self.option("with") - for group in groups.split(",") - ] - ) - only_groups.extend( - [ - group.strip() - for groups in self.option("only") - for group in groups.split(",") - ] - ) - - if self.option("default"): - only_groups.append("default") + if not Exporter.is_format_supported(fmt): + raise ValueError(f"Invalid export format: {fmt}") output = self.option("output") @@ -111,7 +60,7 @@ def handle(self) -> None: elif self.io.is_verbose(): options.append(("-v", None)) - self.call("lock", " ".join(options)) + self.call("lock", " ".join(options)) # type: ignore[arg-type] if not locker.is_fresh(): self.line_error( @@ -124,10 +73,10 @@ def handle(self) -> None: ) exporter = Exporter(self.poetry) - exporter.with_groups(included_groups) - exporter.without_groups(excluded_groups) - exporter.only_groups(only_groups) + print(exporter, "<<<<<<<") + exporter.only_groups(list(self.activated_groups)) exporter.with_extras(self.option("extras")) exporter.with_hashes(not self.option("without-hashes")) exporter.with_credentials(self.option("with-credentials")) + exporter.with_urls(not self.option("without-urls")) exporter.export(fmt, self.poetry.file.parent, output or self.io) diff --git a/src/poetry_export_plugin/exporter.py b/src/poetry_plugin_export/exporter.py similarity index 61% rename from src/poetry_export_plugin/exporter.py rename to src/poetry_plugin_export/exporter.py index 827bd82..562aad5 100644 --- a/src/poetry_export_plugin/exporter.py +++ b/src/poetry_plugin_export/exporter.py @@ -1,14 +1,16 @@ +from __future__ import annotations + import urllib.parse -from pathlib import Path from typing import TYPE_CHECKING -from typing import List -from typing import Optional -from typing import Union +from typing import Iterable + +from cleo.io.io import IO if TYPE_CHECKING: - from cleo.io.io import IO + from pathlib import Path + from poetry.poetry import Poetry @@ -18,56 +20,54 @@ class Exporter: """ FORMAT_REQUIREMENTS_TXT = "requirements.txt" - #: The names of the supported export formats. - ACCEPTED_FORMATS = (FORMAT_REQUIREMENTS_TXT,) ALLOWED_HASH_ALGORITHMS = ("sha256", "sha384", "sha512") - def __init__(self, poetry: "Poetry") -> None: - self._poetry = poetry - self._without_groups: Optional[List[str]] = None - self._with_groups: Optional[List[str]] = None - self._only_groups: Optional[List[str]] = None - self._extras: Optional[List[str]] = None - self._with_hashes: bool = True - self._with_credentials: bool = False + EXPORT_METHODS = {FORMAT_REQUIREMENTS_TXT: "_export_requirements_txt"} - def without_groups(self, groups: List[str]) -> "Exporter": - self._without_groups = groups + def __init__(self, poetry: Poetry) -> None: + self._poetry = poetry + self._with_hashes = True + self._with_credentials = False + self._with_urls = True + self._extras: list[str] = [] + self._groups: Iterable[str] | None = None - return self + @classmethod + def is_format_supported(cls, fmt: str) -> bool: + return fmt in cls.EXPORT_METHODS - def with_groups(self, groups: List[str]) -> "Exporter": - self._with_groups = groups + def with_extras(self, extras: list[str]) -> Exporter: + self._extras = extras return self - def only_groups(self, groups: List[str]) -> "Exporter": - self._only_groups = groups + def only_groups(self, groups: Iterable[str]) -> Exporter: + self._groups = groups return self - def with_extras(self, extras: List[str]) -> "Exporter": - self._extras = extras + def with_urls(self, with_urls: bool = True) -> Exporter: + self._with_urls = with_urls return self - def with_hashes(self, with_hashes: bool = True) -> "Exporter": + def with_hashes(self, with_hashes: bool = True) -> Exporter: self._with_hashes = with_hashes return self - def with_credentials(self, with_credentials: bool = True) -> "Exporter": + def with_credentials(self, with_credentials: bool = True) -> Exporter: self._with_credentials = with_credentials return self - def export(self, fmt: str, cwd: Path, output: Union["IO", str]) -> None: - if fmt not in self.ACCEPTED_FORMATS: + def export(self, fmt: str, cwd: Path, output: IO | str) -> None: + if not self.is_format_supported(fmt): raise ValueError(f"Invalid export format: {fmt}") - getattr(self, "_export_{}".format(fmt.replace(".", "_")))(cwd, output) + getattr(self, self.EXPORT_METHODS[fmt])(cwd, output) - def _export_requirements_txt(self, cwd: Path, output: Union["IO", str]) -> None: + def _export_requirements_txt(self, cwd: Path, output: IO | str) -> None: from cleo.io.null_io import NullIO from poetry.core.packages.utils.utils import path_to_url from poetry.puzzle.solver import Solver @@ -78,22 +78,12 @@ def _export_requirements_txt(self, cwd: Path, output: Union["IO", str]) -> None: content = "" dependency_lines = set() - if self._without_groups or self._with_groups or self._only_groups: - if self._with_groups: - # Default dependencies and opted-in optional dependencies - root = self._poetry.package.with_dependency_groups(self._with_groups) - elif self._without_groups: - # Default dependencies without selected groups - root = self._poetry.package.without_dependency_groups( - self._without_groups - ) - else: - # Only selected groups - root = self._poetry.package.with_dependency_groups( - self._only_groups, only=True - ) + if self._groups is not None: + root = self._poetry.package.with_dependency_groups( + list(self._groups), only=True + ) else: - root = self._poetry.package.with_dependency_groups(["default"], only=True) + root = self._poetry.package.without_optional_dependency_groups() locked_repository = self._poetry.locker.locked_repository(True) @@ -106,11 +96,19 @@ def _export_requirements_txt(self, cwd: Path, output: Union["IO", str]) -> None: solver.provider.load_deferred(False) ops = solver.solve().calculate_operations() - packages = sorted([op.package for op in ops], key=lambda package: package.name) + packages = sorted((op.package for op in ops), key=lambda pkg: pkg.name) + + # Get project dependencies. + if self._groups is not None: + root_package = self._poetry.package.with_dependency_groups( + list(self._groups), only=True + ) + else: + root_package = self._poetry.package.without_optional_dependency_groups() for dependency_package in self._poetry.locker.get_project_dependency_packages( - project_requires=root.all_requires, - dev=True, + project_requires=root_package.all_requires, + project_python_marker=root_package.python_marker, extras=self._extras, ): line = "" @@ -133,16 +131,15 @@ def _export_requirements_txt(self, cwd: Path, output: Union["IO", str]) -> None: if is_direct_remote_reference: line = requirement elif is_direct_local_reference: - dependency_uri = path_to_url(package.source_url) - line = f"{package.name} @ {dependency_uri}" + dependency_uri = path_to_url(dependency.source_url) + line = f"{dependency.name} @ {dependency_uri}" else: line = f"{package.name}=={package.version}" - if not is_direct_remote_reference: - if ";" in requirement: - markers = requirement.split(";", 1)[1].strip() - if markers: - line += f" ; {markers}" + if not is_direct_remote_reference and ";" in requirement: + markers = requirement.split(";", 1)[1].strip() + if markers: + line += f" ; {markers}" if ( not is_direct_remote_reference @@ -167,15 +164,14 @@ def _export_requirements_txt(self, cwd: Path, output: Union["IO", str]) -> None: if hashes: line += " \\\n" for i, h in enumerate(hashes): - line += " --hash={}{}".format( - h, " \\\n" if i < len(hashes) - 1 else "" - ) + suffix = " \\\n" if i < len(hashes) - 1 else "" + line += f" --hash={h}{suffix}" dependency_lines.add(line) content += "\n".join(sorted(dependency_lines)) content += "\n" - if indexes: + if indexes and self._with_urls: # If we have extra indexes, we add them to the beginning of the output indexes_header = "" for index in sorted(indexes): @@ -213,11 +209,10 @@ def _export_requirements_txt(self, cwd: Path, output: Union["IO", str]) -> None: self._output(content, cwd, output) - def _output(self, content: str, cwd: Path, output: Union["IO", str]) -> None: - decoded = content - try: - output.write(decoded) - except AttributeError: + def _output(self, content: str, cwd: Path, output: IO | str) -> None: + if isinstance(output, IO): + output.write(content) + else: filepath = cwd / output with filepath.open("w", encoding="utf-8") as f: - f.write(decoded) + f.write(content) diff --git a/src/poetry_plugin_export/plugins.py b/src/poetry_plugin_export/plugins.py new file mode 100644 index 0000000..e1f2d8d --- /dev/null +++ b/src/poetry_plugin_export/plugins.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +from poetry.plugins.application_plugin import ApplicationPlugin + +from poetry_plugin_export.command import ExportCommand + + +if TYPE_CHECKING: + from poetry.console.application import Application + from poetry.console.commands.command import Command + + +class ExportApplicationPlugin(ApplicationPlugin): + @property + def commands(self) -> list[type[Command]]: + return [ExportCommand] + + def activate(self, application: Application) -> None: + # Removing the existing export command to avoid an error + # until Poetry removes the export command + # and uses this plugin instead. + + # If you're checking this code out to get inspiration + # for your own plugins: DON'T DO THIS! + if application.command_loader.has("export"): + del application.command_loader._factories["export"] + + super().activate(application=application) diff --git a/src/poetry_export_plugin/console/__init__.py b/tests/command/__init__.py similarity index 100% rename from src/poetry_export_plugin/console/__init__.py rename to tests/command/__init__.py diff --git a/tests/console/conftest.py b/tests/command/conftest.py similarity index 66% rename from tests/console/conftest.py rename to tests/command/conftest.py index 264a769..0b22530 100644 --- a/tests/console/conftest.py +++ b/tests/command/conftest.py @@ -1,4 +1,7 @@ +from __future__ import annotations + from pathlib import Path +from typing import TYPE_CHECKING import pytest @@ -7,27 +10,43 @@ from poetry.installation import Installer from poetry.utils.env import MockEnv -from tests.helpers import TestApplication +from tests.helpers import PoetryTestApplication from tests.helpers import TestExecutor +if TYPE_CHECKING: + from poetry.installation.executor import Executor + from poetry.poetry import Poetry + from poetry.utils.env import Env + + from tests.types import CommandTesterFactory + + @pytest.fixture -def app(poetry): - app_ = TestApplication(poetry) +def app(poetry: Poetry) -> PoetryTestApplication: + app_ = PoetryTestApplication(poetry) return app_ @pytest.fixture -def env(tmp_dir): +def env(tmp_dir: str) -> MockEnv: path = Path(tmp_dir) / ".venv" path.mkdir(parents=True) return MockEnv(path=path, is_venv=True) @pytest.fixture -def command_tester_factory(app, env): - def _tester(command, poetry=None, installer=None, executor=None, environment=None): +def command_tester_factory( + app: PoetryTestApplication, env: MockEnv +) -> CommandTesterFactory: + def _tester( + command: str, + poetry: Poetry | None = None, + installer: Installer | None = None, + executor: Executor | None = None, + environment: Env | None = None, + ) -> CommandTester: app._load_plugins(NullIO()) command = app.find(command) @@ -69,6 +88,6 @@ def _tester(command, poetry=None, installer=None, executor=None, environment=Non @pytest.fixture -def do_lock(command_tester_factory, poetry): +def do_lock(command_tester_factory: CommandTesterFactory, poetry: Poetry) -> None: command_tester_factory("lock").execute() assert poetry.locker.lock.exists() diff --git a/tests/console/test_export.py b/tests/command/test_command_export.py similarity index 53% rename from tests/console/test_export.py rename to tests/command/test_command_export.py index 6e55041..9ceec95 100644 --- a/tests/console/test_export.py +++ b/tests/command/test_command_export.py @@ -1,10 +1,25 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals +from __future__ import annotations + +from typing import TYPE_CHECKING +from unittest.mock import Mock import pytest from poetry.core.packages.package import Package +from poetry_plugin_export.exporter import Exporter +from tests.markers import MARKER_PY + + +if TYPE_CHECKING: + from _pytest.monkeypatch import MonkeyPatch + from cleo.testers.command_tester import CommandTester + from poetry.poetry import Poetry + from poetry.repositories import Repository + + from tests.types import CommandTesterFactory + from tests.types import ProjectFactory + PYPROJECT_CONTENT = """\ [tool.poetry] @@ -31,7 +46,7 @@ # Requirements [tool.poetry.dependencies] -python = "~2.7 || ^3.4" +python = "~2.7 || ^3.6" foo = "^1.0" bar = { version = "^1.1", optional = true } @@ -41,22 +56,24 @@ @pytest.fixture(autouse=True) -def setup(repo): +def setup(repo: Repository) -> None: repo.add_package(Package("foo", "1.0.0")) repo.add_package(Package("bar", "1.1.0")) @pytest.fixture -def poetry(project_factory): +def poetry(project_factory: ProjectFactory): return project_factory(name="export", pyproject_content=PYPROJECT_CONTENT) @pytest.fixture -def tester(command_tester_factory, poetry): +def tester( + command_tester_factory: CommandTesterFactory, poetry: Poetry +) -> CommandTester: return command_tester_factory("export", poetry=poetry) -def _export_requirements(tester, poetry): +def _export_requirements(tester: CommandTester, poetry: Poetry) -> None: tester.execute("--format requirements.txt --output requirements.txt") requirements = poetry.file.parent / "requirements.txt" @@ -67,49 +84,68 @@ def _export_requirements(tester, poetry): assert poetry.locker.lock.exists() - expected = """\ -foo==1.0.0 + expected = f"""\ +foo==1.0.0 ; {MARKER_PY} """ assert expected == content -def test_export_exports_requirements_txt_file_locks_if_no_lock_file(tester, poetry): +def test_export_exports_requirements_txt_file_locks_if_no_lock_file( + tester: CommandTester, poetry: Poetry +): assert not poetry.locker.lock.exists() _export_requirements(tester, poetry) assert "The lock file does not exist. Locking." in tester.io.fetch_error() -def test_export_exports_requirements_txt_uses_lock_file(tester, poetry, do_lock): +def test_export_exports_requirements_txt_uses_lock_file( + tester: CommandTester, poetry: Poetry, do_lock: None +): _export_requirements(tester, poetry) assert "The lock file does not exist. Locking." not in tester.io.fetch_error() -def test_export_fails_on_invalid_format(tester, do_lock): +def test_export_fails_on_invalid_format(tester: CommandTester, do_lock: None): with pytest.raises(ValueError): tester.execute("--format invalid") -def test_export_prints_to_stdout_by_default(tester, do_lock): +def test_export_prints_to_stdout_by_default(tester: CommandTester, do_lock: None): tester.execute("--format requirements.txt") - expected = """\ -foo==1.0.0 + expected = f"""\ +foo==1.0.0 ; {MARKER_PY} """ assert expected == tester.io.fetch_output() -def test_export_uses_requirements_txt_format_by_default(tester, do_lock): +def test_export_uses_requirements_txt_format_by_default( + tester: CommandTester, do_lock: None +): tester.execute() - expected = """\ -foo==1.0.0 + expected = f"""\ +foo==1.0.0 ; {MARKER_PY} """ assert expected == tester.io.fetch_output() -def test_export_includes_extras_by_flag(tester, do_lock): +def test_export_includes_extras_by_flag(tester: CommandTester, do_lock: None): tester.execute("--format requirements.txt --extras feature_bar") - expected = """\ -bar==1.1.0 -foo==1.0.0 + expected = f"""\ +bar==1.1.0 ; {MARKER_PY} +foo==1.0.0 ; {MARKER_PY} """ assert expected == tester.io.fetch_output() + + +def test_export_with_urls( + monkeypatch: MonkeyPatch, tester: CommandTester, poetry: Poetry +): + """ + We are just validating that the option gets passed. The option itself is tested in + the Exporter test. + """ + mock_export = Mock() + monkeypatch.setattr(Exporter, "with_urls", mock_export) + tester.execute("--without-urls") + mock_export.assert_called_once_with(False) diff --git a/tests/conftest.py b/tests/conftest.py index ef14c63..c1da348 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,10 +1,13 @@ +from __future__ import annotations + import shutil import sys import tempfile from pathlib import Path +from typing import TYPE_CHECKING from typing import Any -from typing import Dict +from typing import Iterator import pytest @@ -13,47 +16,55 @@ from poetry.core.packages.package import Package from poetry.factory import Factory from poetry.layouts import layout -from poetry.repositories.pool import Pool -from poetry.repositories.repository import Repository +from poetry.repositories import Pool +from poetry.repositories import Repository from poetry.utils.env import SystemEnv from tests.helpers import TestLocker +if TYPE_CHECKING: + from poetry.poetry import Poetry + from pytest_mock import MockerFixture + + from tests.types import FixtureDirGetter + from tests.types import ProjectFactory + + class Config(BaseConfig): def get(self, setting_name: str, default: Any = None) -> Any: self.merge(self._config_source.config) self.merge(self._auth_config_source.config) - return super(Config, self).get(setting_name, default=default) + return super().get(setting_name, default=default) - def raw(self) -> Dict[str, Any]: + def raw(self) -> dict[str, Any]: self.merge(self._config_source.config) self.merge(self._auth_config_source.config) - return super(Config, self).raw() + return super().raw() - def all(self) -> Dict[str, Any]: + def all(self) -> dict[str, Any]: self.merge(self._config_source.config) self.merge(self._auth_config_source.config) - return super(Config, self).all() + return super().all() @pytest.fixture -def config_cache_dir(tmp_dir): +def config_cache_dir(tmp_dir: str) -> Path: path = Path(tmp_dir) / ".cache" / "pypoetry" path.mkdir(parents=True) return path @pytest.fixture -def config_virtualenvs_path(config_cache_dir): +def config_virtualenvs_path(config_cache_dir: Path) -> Path: return config_cache_dir / "virtualenvs" @pytest.fixture -def config_source(config_cache_dir): +def config_source(config_cache_dir: Path) -> DictConfigSource: source = DictConfigSource() source.add_property("cache-dir", str(config_cache_dir)) @@ -61,14 +72,18 @@ def config_source(config_cache_dir): @pytest.fixture -def auth_config_source(): +def auth_config_source() -> DictConfigSource: source = DictConfigSource() return source @pytest.fixture -def config(config_source, auth_config_source, mocker): +def config( + config_source: DictConfigSource, + auth_config_source: DictConfigSource, + mocker: MockerFixture, +) -> Config: import keyring from keyring.backends.fail import Keyring @@ -87,7 +102,7 @@ def config(config_source, auth_config_source, mocker): @pytest.fixture -def tmp_dir(): +def tmp_dir() -> Iterator[str]: dir_ = tempfile.mkdtemp(prefix="poetry_") yield dir_ @@ -96,51 +111,62 @@ def tmp_dir(): @pytest.fixture -def fixture_dir(): - def _fixture_dir(fixture): - return Path(__file__).parent.joinpath("fixtures").joinpath(fixture) +def fixture_base() -> Path: + return Path(__file__).parent.joinpath("fixtures") + + +@pytest.fixture +def fixture_dir(fixture_base: Path) -> FixtureDirGetter: + def _fixture_dir(name: str) -> Path: + return fixture_base / name return _fixture_dir @pytest.fixture() -def repo(): +def repo() -> Repository: return Repository() @pytest.fixture -def installed(): +def installed() -> Repository: return Repository() @pytest.fixture(scope="session") -def current_env(): +def current_env() -> SystemEnv: return SystemEnv(Path(sys.executable)) @pytest.fixture(scope="session") -def current_python(current_env): +def current_python(current_env: SystemEnv) -> tuple[int, int, int]: return current_env.version_info[:3] @pytest.fixture(scope="session") -def default_python(current_python): - return "^{}".format(".".join(str(v) for v in current_python[:2])) +def default_python(current_python: tuple[int, int, int]) -> str: + return "^" + ".".join(str(v) for v in current_python[:2]) @pytest.fixture -def project_factory(tmp_dir, config, repo, installed, default_python): +def project_factory( + tmp_dir: str, + config: Config, + repo: Repository, + installed: Repository, + default_python: str, +) -> ProjectFactory: workspace = Path(tmp_dir) def _factory( - name=None, - dependencies=None, - dev_dependencies=None, - pyproject_content=None, - poetry_lock_content=None, - install_deps=True, - ): - project_dir = workspace / "poetry-fixture-{}".format(name) + name: str | None = None, + dependencies: dict[str, str] | None = None, + dev_dependencies: dict[str, str] | None = None, + pyproject_content: str | None = None, + poetry_lock_content: str | None = None, + install_deps: bool = True, + ) -> Poetry: + project_dir = workspace / f"poetry-fixture-{name}" dependencies = dependencies or {} dev_dependencies = dev_dependencies or {} @@ -167,9 +193,7 @@ def _factory( poetry = Factory().create_poetry(project_dir) - locker = TestLocker( - poetry.locker.lock.path, poetry.locker._local_config - ) # noqa + locker = TestLocker(poetry.locker.lock.path, poetry.locker._local_config) locker.write() poetry.set_locker(locker) diff --git a/tests/console/__init__.py b/tests/console/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/fixtures/project_with_setup/setup.py b/tests/fixtures/project_with_setup/setup.py index 0f9e0d0..c4b8425 100644 --- a/tests/fixtures/project_with_setup/setup.py +++ b/tests/fixtures/project_with_setup/setup.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +from __future__ import annotations from setuptools import setup diff --git a/tests/helpers.py b/tests/helpers.py index eef9000..8ea5922 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,3 +1,8 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING +from typing import Any + from poetry.console.application import Application from poetry.core.toml.file import TOMLFile from poetry.factory import Factory @@ -5,12 +10,21 @@ from poetry.packages import Locker -class TestApplication(Application): - def __init__(self, poetry): +if TYPE_CHECKING: + from pathlib import Path + + from poetry.core.packages.package import Package + from poetry.installation.operations import OperationTypes + from poetry.poetry import Poetry + from tomlkit.toml_document import TOMLDocument + + +class PoetryTestApplication(Application): + def __init__(self, poetry: Poetry): super().__init__() self._poetry = poetry - def reset_poetry(self): + def reset_poetry(self) -> None: poetry = self._poetry self._poetry = Factory().create_poetry(self._poetry.file.path.parent) self._poetry.set_pool(poetry.pool) @@ -21,7 +35,7 @@ def reset_poetry(self): class TestLocker(Locker): - def __init__(self, lock, local_config): # noqa + def __init__(self, lock: str | Path, local_config: dict): self._lock = TOMLFile(lock) self._local_config = local_config self._lock_data = None @@ -30,26 +44,26 @@ def __init__(self, lock, local_config): # noqa self._lock_data = None self._write = False - def write(self, write=True): + def write(self, write: bool = True) -> None: self._write = write - def is_locked(self): + def is_locked(self) -> bool: return self._locked - def locked(self, is_locked=True): + def locked(self, is_locked: bool = True) -> TestLocker: self._locked = is_locked return self - def mock_lock_data(self, data): + def mock_lock_data(self, data: dict) -> None: self.locked() self._lock_data = data - def is_fresh(self): + def is_fresh(self) -> bool: return True - def _write_lock_data(self, data): + def _write_lock_data(self, data: TOMLDocument) -> None: if self._write: super()._write_lock_data(data) self._locked = True @@ -59,7 +73,7 @@ def _write_lock_data(self, data): class TestExecutor(Executor): - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any): super().__init__(*args, **kwargs) self._installs = [] @@ -67,28 +81,28 @@ def __init__(self, *args, **kwargs): self._uninstalls = [] @property - def installations(self): + def installations(self) -> list[Package]: return self._installs @property - def updates(self): + def updates(self) -> list[Package]: return self._updates @property - def removals(self): + def removals(self) -> list[Package]: return self._uninstalls - def _do_execute_operation(self, operation): + def _do_execute_operation(self, operation: OperationTypes) -> None: super()._do_execute_operation(operation) if not operation.skipped: - getattr(self, "_{}s".format(operation.job_type)).append(operation.package) + getattr(self, f"_{operation.job_type}s").append(operation.package) - def _execute_install(self, operation): + def _execute_install(self, operation: OperationTypes) -> int: return 0 - def _execute_update(self, operation): + def _execute_update(self, operation: OperationTypes) -> int: return 0 - def _execute_remove(self, operation): + def _execute_remove(self, operation: OperationTypes) -> int: return 0 diff --git a/tests/markers.py b/tests/markers.py new file mode 100644 index 0000000..65c9dd0 --- /dev/null +++ b/tests/markers.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from poetry.core.version.markers import parse_marker + + +MARKER_WIN32 = parse_marker('sys_platform == "win32"') +MARKER_WINDOWS = parse_marker('platform_system == "Windows"') +MARKER_LINUX = parse_marker('sys_platform == "linux"') +MARKER_DARWIN = parse_marker('sys_platform == "darwin"') + +MARKER_PY27 = parse_marker('python_version >= "2.7" and python_version < "2.8"') + +MARKER_PY36 = parse_marker('python_version >= "3.6" and python_version < "4.0"') +MARKER_PY36_38 = parse_marker('python_version >= "3.6" and python_version < "3.8"') +MARKER_PY36_ONLY = parse_marker('python_version >= "3.6" and python_version < "3.7"') + +MARKER_PY37 = parse_marker('python_version >= "3.7" and python_version < "4.0"') +MARKER_PY37_PY400 = parse_marker( + 'python_version >= "3.7" and python_full_version < "4.0.0"' +) + +MARKER_PY = MARKER_PY27.union(MARKER_PY36) + +MARKER_PY_WIN32 = MARKER_PY.intersect(MARKER_WIN32) +MARKER_PY_WINDOWS = MARKER_PY.intersect(MARKER_WINDOWS) +MARKER_PY_LINUX = MARKER_PY.intersect(MARKER_LINUX) +MARKER_PY_DARWIN = MARKER_PY.intersect(MARKER_DARWIN) diff --git a/tests/test_exporter.py b/tests/test_exporter.py index cf18b7c..cd5ea74 100644 --- a/tests/test_exporter.py +++ b/tests/test_exporter.py @@ -1,85 +1,108 @@ +from __future__ import annotations + import sys from pathlib import Path +from typing import TYPE_CHECKING +from typing import Any +from typing import Iterator import pytest from poetry.core.packages.dependency import Dependency -from poetry.core.packages.dependency_group import DependencyGroup from poetry.core.toml.file import TOMLFile +from poetry.core.version.markers import parse_marker from poetry.factory import Factory -from poetry.packages.locker import Locker as BaseLocker +from poetry.packages import Locker as BaseLocker from poetry.repositories.legacy_repository import LegacyRepository +from poetry.utils.exporter import Exporter + +from tests.markers import MARKER_PY +from tests.markers import MARKER_PY27 +from tests.markers import MARKER_PY36 +from tests.markers import MARKER_PY36_38 +from tests.markers import MARKER_PY36_ONLY +from tests.markers import MARKER_PY37 +from tests.markers import MARKER_PY37_PY400 +from tests.markers import MARKER_PY_DARWIN +from tests.markers import MARKER_PY_LINUX +from tests.markers import MARKER_PY_WIN32 +from tests.markers import MARKER_PY_WINDOWS +from tests.markers import MARKER_WIN32 +from tests.markers import MARKER_WINDOWS + -from poetry_export_plugin.exporter import Exporter +if TYPE_CHECKING: + from _pytest.capture import CaptureFixture + from poetry.poetry import Poetry + from pytest_mock import MockerFixture + + from tests.conftest import Config + from tests.types import FixtureDirGetter class Locker(BaseLocker): - def __init__(self): + def __init__(self) -> None: self._lock = TOMLFile(Path.cwd().joinpath("poetry.lock")) self._locked = True self._content_hash = self._get_content_hash() - def locked(self, is_locked=True): + def locked(self, is_locked: bool = True) -> Locker: self._locked = is_locked return self - def mock_lock_data(self, data): + def mock_lock_data(self, data: dict[str, Any]): self._lock_data = data - def is_locked(self): + def is_locked(self) -> bool: return self._locked - def is_fresh(self): + def is_fresh(self) -> bool: return True - def _get_content_hash(self): + def _get_content_hash(self) -> str: return "123456789" @pytest.fixture -def working_directory(): +def working_directory() -> Path: return Path(__file__).parent.parent @pytest.fixture(autouse=True) -def mock_path_cwd(mocker, working_directory): +def mock_path_cwd( + mocker: MockerFixture, working_directory: Path +) -> Iterator[MockerFixture]: yield mocker.patch("pathlib.Path.cwd", return_value=working_directory) @pytest.fixture() -def locker(): +def locker() -> Locker: return Locker() @pytest.fixture -def poetry(fixture_dir, locker): +def poetry(fixture_dir: FixtureDirGetter, locker: Locker) -> Poetry: p = Factory().create_poetry(fixture_dir("sample_project")) p._locker = locker return p -def set_package_requires(poetry, skip=None): +def set_package_requires(poetry: Poetry, skip: set[str] | None = None) -> None: skip = skip or set() packages = poetry.locker.locked_repository(with_dev_reqs=True).packages package = poetry.package.with_dependency_groups([], only=True) - dev_group = DependencyGroup("dev") for pkg in packages: if pkg.name not in skip: - if pkg.category == "dev": - dev_group.add_dependency(pkg.to_dependency()) - else: - package.add_dependency(pkg.to_dependency()) - - package.add_dependency_group(dev_group) + package.add_dependency(pkg.to_dependency()) poetry._package = package def test_exporter_can_export_requirements_txt_with_standard_packages( - tmp_dir, poetry, mocker + tmp_dir: str, poetry: Poetry ): poetry.locker.mock_lock_data( { @@ -109,22 +132,21 @@ def test_exporter_can_export_requirements_txt_with_standard_packages( set_package_requires(poetry) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -bar==4.5.6 -foo==1.2.3 + expected = f"""\ +bar==4.5.6 ; {MARKER_PY} +foo==1.2.3 ; {MARKER_PY} """ - assert expected == content + assert content == expected def test_exporter_can_export_requirements_txt_with_standard_packages_and_markers( - tmp_dir, poetry + tmp_dir: str, poetry: Poetry ): poetry.locker.mock_lock_data( { @@ -164,22 +186,21 @@ def test_exporter_can_export_requirements_txt_with_standard_packages_and_markers set_package_requires(poetry) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -bar==4.5.6 -baz==7.8.9 ; sys_platform == "win32" -foo==1.2.3 ; python_version < "3.7" + expected = f"""\ +bar==4.5.6 ; {MARKER_PY} +baz==7.8.9 ; {MARKER_PY_WIN32} +foo==1.2.3 ; {MARKER_PY27.union(MARKER_PY36_ONLY)} """ - assert expected == content + assert content == expected -def test_exporter_can_export_requirements_txt_poetry(tmp_dir, poetry): +def test_exporter_can_export_requirements_txt_poetry(tmp_dir: str, poetry: Poetry): """Regression test for #3254""" poetry.locker.mock_lock_data( @@ -257,15 +278,14 @@ def test_exporter_can_export_requirements_txt_poetry(tmp_dir, poetry): ) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() # The dependency graph: - # junit-xml 1.9 Creates JUnit XML test result documents that can be read by tools such as Jenkins - # └── six * + # junit-xml 1.9 Creates JUnit XML test result documents that can be read by tools + # └── six * such as Jenkins # poetry 1.1.4 Python dependency management and packaging made easy. # ├── keyring >=21.2.0,<22.0.0 # │ ├── importlib-metadata >=1 @@ -277,16 +297,18 @@ def test_exporter_can_export_requirements_txt_poetry(tmp_dir, poetry): # │ │ └── six >=1.4.1 # │ └── jeepney >=0.6 (circular dependency aborted here) expected = { - "poetry": Dependency.create_from_pep_508("poetry==1.1.4"), - "junit-xml": Dependency.create_from_pep_508("junit-xml==1.9"), - "keyring": Dependency.create_from_pep_508("keyring==21.8.0"), + "poetry": Dependency.create_from_pep_508(f"poetry==1.1.4; {MARKER_PY}"), + "junit-xml": Dependency.create_from_pep_508(f"junit-xml==1.9 ; {MARKER_PY}"), + "keyring": Dependency.create_from_pep_508(f"keyring==21.8.0 ; {MARKER_PY}"), "secretstorage": Dependency.create_from_pep_508( - "secretstorage==3.3.0; sys_platform=='linux'" + f"secretstorage==3.3.0 ; {MARKER_PY_LINUX}" ), "cryptography": Dependency.create_from_pep_508( - "cryptography==3.2; sys_platform=='linux'" + f"cryptography==3.2 ; {MARKER_PY_LINUX}" + ), + "six": Dependency.create_from_pep_508( + f"six==1.15.0 ; {MARKER_PY.union(MARKER_PY_LINUX)}" ), - "six": Dependency.create_from_pep_508("six==1.15.0"), } for line in content.strip().split("\n"): @@ -297,7 +319,7 @@ def test_exporter_can_export_requirements_txt_poetry(tmp_dir, poetry): assert dependency.marker == expected_dependency.marker -def test_exporter_can_export_requirements_txt_pyinstaller(tmp_dir, poetry): +def test_exporter_can_export_requirements_txt_pyinstaller(tmp_dir: str, poetry: Poetry): """Regression test for #3254""" poetry.locker.mock_lock_data( @@ -343,25 +365,29 @@ def test_exporter_can_export_requirements_txt_pyinstaller(tmp_dir, poetry): set_package_requires(poetry, skip={"altgraph", "macholib"}) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() # Rationale for the results: - # * PyInstaller has an explicit dependency on altgraph, so it must always be installed. + # * PyInstaller has an explicit dependency on altgraph, so it must always be + # installed. # * PyInstaller requires macholib on Darwin, which in turn requires altgraph. # The dependency graph: - # pyinstaller 4.0 PyInstaller bundles a Python application and all its dependencies into a single package. - # ├── altgraph * + # pyinstaller 4.0 PyInstaller bundles a Python application and all its + # ├── altgraph * dependencies into a single package. # ├── macholib >=1.8 -- only on Darwin # │ └── altgraph >=0.15 expected = { - "pyinstaller": Dependency.create_from_pep_508("pyinstaller==4.0"), - "altgraph": Dependency.create_from_pep_508("altgraph==0.17"), + "pyinstaller": Dependency.create_from_pep_508( + f"pyinstaller==4.0 ; {MARKER_PY}" + ), + "altgraph": Dependency.create_from_pep_508( + f"altgraph==0.17 ; {MARKER_PY.union(MARKER_PY_DARWIN)}" + ), "macholib": Dependency.create_from_pep_508( - "macholib==1.8; sys_platform == 'darwin'" + f"macholib==1.8 ; {MARKER_PY_DARWIN}" ), } @@ -374,7 +400,7 @@ def test_exporter_can_export_requirements_txt_pyinstaller(tmp_dir, poetry): def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers( - tmp_dir, poetry + tmp_dir: str, poetry: Poetry ): poetry.locker.mock_lock_data( { @@ -424,22 +450,21 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers( set_package_requires(poetry, skip={"b", "c", "d"}) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() + marker_py = MARKER_PY27.union(MARKER_PY36_ONLY) + marker_py_win32 = marker_py.intersect(MARKER_WIN32) + marker_py_windows = marker_py.intersect(MARKER_WINDOWS) + expected = { - "a": Dependency.create_from_pep_508("a==1.2.3 ; python_version < '3.7'"), - "b": Dependency.create_from_pep_508( - "b==4.5.6 ; platform_system == 'Windows' and python_version < '3.7'" - ), - "c": Dependency.create_from_pep_508( - "c==7.8.9 ; sys_platform == 'win32' and python_version < '3.7'" - ), + "a": Dependency.create_from_pep_508(f"a==1.2.3 ; {marker_py}"), + "b": Dependency.create_from_pep_508(f"b==4.5.6 ; {marker_py_windows}"), + "c": Dependency.create_from_pep_508(f"c==7.8.9 ; {marker_py_win32}"), "d": Dependency.create_from_pep_508( - "d==0.0.1 ; platform_system == 'Windows' and python_version < '3.7' or sys_platform == 'win32' and python_version < '3.7'" + f"d==0.0.1 ; {marker_py_win32.union(marker_py_windows)}" ), } @@ -454,11 +479,23 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers( @pytest.mark.parametrize( - "dev,lines", - [(False, ['a==1.2.3 ; python_version < "3.8"']), (True, ["a==1.2.3", "b==4.5.6"])], + ["dev", "lines"], + [ + ( + False, + [f"a==1.2.3 ; {MARKER_PY27.union(MARKER_PY36_38)}"], + ), + ( + True, + [ + f"a==1.2.3 ; {MARKER_PY27.union(MARKER_PY36_38).union(MARKER_PY36)}", + f"b==4.5.6 ; {MARKER_PY}", + ], + ), + ], ) def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers_any( - tmp_dir, poetry, dev, lines + tmp_dir: str, poetry: Poetry, dev: bool, lines: list[str] ): poetry.locker.mock_lock_data( { @@ -487,25 +524,21 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers_a } ) - package = poetry.package.with_dependency_groups([], only=True) - package.add_dependency( + root = poetry.package.with_dependency_groups([], only=True) + root.add_dependency( Factory.create_dependency( - name="a", constraint=dict(version="^1.2.3", python="<3.8") + name="a", constraint={"version": "^1.2.3", "python": "<3.8"} ) ) - package.add_dependency( + root.add_dependency( Factory.create_dependency( - name="b", constraint=dict(version="^4.5.6"), groups=["dev"] + name="b", constraint={"version": "^4.5.6"}, groups=["dev"] ) ) - - poetry._package = package + poetry._package = root exporter = Exporter(poetry) - if dev: - exporter.with_groups(["dev"]) - - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") + exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=dev) with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() @@ -514,7 +547,7 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_and_markers_a def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes( - tmp_dir, poetry + tmp_dir: str, poetry: Poetry ): poetry.locker.mock_lock_data( { @@ -544,25 +577,23 @@ def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes( set_package_requires(poetry) exporter = Exporter(poetry) - exporter.with_hashes(True) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -bar==4.5.6 \\ + expected = f"""\ +bar==4.5.6 ; {MARKER_PY} \\ --hash=sha256:67890 -foo==1.2.3 \\ +foo==1.2.3 ; {MARKER_PY} \\ --hash=sha256:12345 """ - assert expected == content + assert content == expected -def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes_disabled( - tmp_dir, poetry +def test_exporter_requirements_txt_with_standard_packages_and_hashes_disabled( + tmp_dir: str, poetry: Poetry ): poetry.locker.mock_lock_data( { @@ -592,23 +623,23 @@ def test_exporter_can_export_requirements_txt_with_standard_packages_and_hashes_ set_package_requires(poetry) exporter = Exporter(poetry) - exporter.with_hashes(False) - - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") + exporter.export( + "requirements.txt", Path(tmp_dir), "requirements.txt", with_hashes=False + ) with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -bar==4.5.6 -foo==1.2.3 + expected = f"""\ +bar==4.5.6 ; {MARKER_PY} +foo==1.2.3 ; {MARKER_PY} """ - assert expected == content + assert content == expected def test_exporter_exports_requirements_txt_without_dev_packages_by_default( - tmp_dir, poetry + tmp_dir: str, poetry: Poetry ): poetry.locker.mock_lock_data( { @@ -635,35 +666,24 @@ def test_exporter_exports_requirements_txt_without_dev_packages_by_default( }, } ) - package = poetry.package.with_dependency_groups([], only=True) - package.add_dependency( - Factory.create_dependency(name="foo", constraint=dict(version="^1.2.3")) - ) - package.add_dependency( - Factory.create_dependency( - name="bar", constraint=dict(version="^4.5.6"), groups=["dev"] - ) - ) - - poetry._package = package + set_package_requires(poetry) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -foo==1.2.3 \\ + expected = f"""\ +foo==1.2.3 ; {MARKER_PY} \\ --hash=sha256:12345 """ - assert expected == content + assert content == expected def test_exporter_exports_requirements_txt_with_dev_packages_if_opted_in( - tmp_dir, poetry + tmp_dir: str, poetry: Poetry ): poetry.locker.mock_lock_data( { @@ -690,37 +710,27 @@ def test_exporter_exports_requirements_txt_with_dev_packages_if_opted_in( }, } ) - package = poetry.package.with_dependency_groups([], only=True) - package.add_dependency( - Factory.create_dependency(name="foo", constraint=dict(version="^1.2.3")) - ) - package.add_dependency( - Factory.create_dependency( - name="bar", constraint=dict(version="^4.5.6"), groups=["dev"] - ) - ) - - poetry._package = package + set_package_requires(poetry) exporter = Exporter(poetry) - exporter.with_groups(["dev"]) - - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") + exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True) with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -bar==4.5.6 \\ + expected = f"""\ +bar==4.5.6 ; {MARKER_PY} \\ --hash=sha256:67890 -foo==1.2.3 \\ +foo==1.2.3 ; {MARKER_PY} \\ --hash=sha256:12345 """ - assert expected == content + assert content == expected -def test_exporter_exports_requirements_txt_without_optional_packages(tmp_dir, poetry): +def test_exporter_exports_requirements_txt_without_optional_packages( + tmp_dir: str, poetry: Poetry +): poetry.locker.mock_lock_data( { "package": [ @@ -734,7 +744,7 @@ def test_exporter_exports_requirements_txt_without_optional_packages(tmp_dir, po { "name": "bar", "version": "4.5.6", - "category": "main", + "category": "dev", "optional": True, "python-versions": "*", }, @@ -746,47 +756,56 @@ def test_exporter_exports_requirements_txt_without_optional_packages(tmp_dir, po }, } ) - package = poetry.package.with_dependency_groups([], only=True) - package.add_dependency( - Factory.create_dependency(name="foo", constraint=dict(version="^1.2.3")) - ) - package.add_dependency( - Factory.create_dependency( - name="bar", constraint=dict(version="^4.5.6", optional=True) - ) - ) - package.extras["foo"] = [ - Factory.create_dependency( - name="bar", constraint=dict(version="^4.5.6", optional=True) - ) - ] - - poetry._package = package + set_package_requires(poetry) exporter = Exporter(poetry) - - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") + exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True) with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -foo==1.2.3 \\ + expected = f"""\ +foo==1.2.3 ; {MARKER_PY} \\ --hash=sha256:12345 """ - assert expected == content + assert content == expected @pytest.mark.parametrize( - "extras,lines", + ["extras", "lines"], [ - (None, ["foo==1.2.3"]), - (["feature_bar"], ["bar==4.5.6", "foo==1.2.3", "spam==0.1.0"]), + ( + None, + [f"foo==1.2.3 ; {MARKER_PY}"], + ), + ( + False, + [f"foo==1.2.3 ; {MARKER_PY}"], + ), + ( + True, + [ + f"bar==4.5.6 ; {MARKER_PY}", + f"foo==1.2.3 ; {MARKER_PY}", + f"spam==0.1.0 ; {MARKER_PY}", + ], + ), + ( + ["feature_bar"], + [ + f"bar==4.5.6 ; {MARKER_PY}", + f"foo==1.2.3 ; {MARKER_PY}", + f"spam==0.1.0 ; {MARKER_PY}", + ], + ), ], ) def test_exporter_exports_requirements_txt_with_optional_packages( - tmp_dir, poetry, extras, lines + tmp_dir: str, + poetry: Poetry, + extras: bool | list[str] | None, + lines: list[str], ): poetry.locker.mock_lock_data( { @@ -825,11 +844,14 @@ def test_exporter_exports_requirements_txt_with_optional_packages( set_package_requires(poetry) exporter = Exporter(poetry) - exporter.with_hashes(False) - if extras: - exporter.with_extras(extras) - - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") + exporter.export( + "requirements.txt", + Path(tmp_dir), + "requirements.txt", + dev=True, + with_hashes=False, + extras=extras, + ) with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() @@ -839,7 +861,9 @@ def test_exporter_exports_requirements_txt_with_optional_packages( assert content.strip() == expected -def test_exporter_can_export_requirements_txt_with_git_packages(tmp_dir, poetry): +def test_exporter_can_export_requirements_txt_with_git_packages( + tmp_dir: str, poetry: Poetry +): poetry.locker.mock_lock_data( { "package": [ @@ -866,20 +890,21 @@ def test_exporter_can_export_requirements_txt_with_git_packages(tmp_dir, poetry) set_package_requires(poetry) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -foo @ git+https://github.com/foo/foo.git@123456 + expected = f"""\ +foo @ git+https://github.com/foo/foo.git@123456 ; {MARKER_PY} """ - assert expected == content + assert content == expected -def test_exporter_can_export_requirements_txt_with_nested_packages(tmp_dir, poetry): +def test_exporter_can_export_requirements_txt_with_nested_packages( + tmp_dir: str, poetry: Poetry +): poetry.locker.mock_lock_data( { "package": [ @@ -914,22 +939,21 @@ def test_exporter_can_export_requirements_txt_with_nested_packages(tmp_dir, poet set_package_requires(poetry, skip={"foo"}) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -bar==4.5.6 -foo @ git+https://github.com/foo/foo.git@123456 + expected = f"""\ +bar==4.5.6 ; {MARKER_PY} +foo @ git+https://github.com/foo/foo.git@123456 ; {MARKER_PY} """ - assert expected == content + assert content == expected def test_exporter_can_export_requirements_txt_with_nested_packages_cyclic( - tmp_dir, poetry + tmp_dir: str, poetry: Poetry ): poetry.locker.mock_lock_data( { @@ -969,23 +993,97 @@ def test_exporter_can_export_requirements_txt_with_nested_packages_cyclic( set_package_requires(poetry, skip={"bar", "baz"}) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -bar==4.5.6 -baz==7.8.9 -foo==1.2.3 + expected = f"""\ +bar==4.5.6 ; {MARKER_PY} +baz==7.8.9 ; {MARKER_PY} +foo==1.2.3 ; {MARKER_PY} +""" + + assert content == expected + + +def test_exporter_can_export_requirements_txt_with_nested_packages_and_multiple_markers( + tmp_dir: str, poetry: Poetry +): + poetry.locker.mock_lock_data( + { + "package": [ + { + "name": "foo", + "version": "1.2.3", + "category": "main", + "optional": False, + "python-versions": "*", + "dependencies": { + "bar": [ + { + "version": ">=1.2.3,<7.8.10", + "markers": 'platform_system != "Windows"', + }, + { + "version": ">=4.5.6,<7.8.10", + "markers": 'platform_system == "Windows"', + }, + ] + }, + }, + { + "name": "bar", + "version": "7.8.9", + "category": "main", + "optional": True, + "python-versions": "*", + "dependencies": { + "baz": { + "version": "!=10.11.12", + "markers": 'platform_system == "Windows"', + } + }, + }, + { + "name": "baz", + "version": "10.11.13", + "category": "main", + "optional": True, + "python-versions": "*", + }, + ], + "metadata": { + "python-versions": "*", + "content-hash": "123456789", + "hashes": {"foo": [], "bar": [], "baz": []}, + }, + } + ) + set_package_requires(poetry) + + exporter = Exporter(poetry) + exporter.export( + "requirements.txt", Path(tmp_dir), "requirements.txt", with_hashes=False + ) + + with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: + content = f.read() + + marker_py_not_windows = MARKER_PY.intersect( + parse_marker('platform_system != "Windows"') + ) + expected = f"""\ +bar==7.8.9 ; {marker_py_not_windows.union(MARKER_PY_WINDOWS)} +baz==10.11.13 ; {MARKER_PY_WINDOWS} +foo==1.2.3 ; {MARKER_PY} """ - assert expected == content + assert content == expected def test_exporter_can_export_requirements_txt_with_git_packages_and_markers( - tmp_dir, poetry + tmp_dir: str, poetry: Poetry ): poetry.locker.mock_lock_data( { @@ -1014,21 +1112,20 @@ def test_exporter_can_export_requirements_txt_with_git_packages_and_markers( set_package_requires(poetry) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -foo @ git+https://github.com/foo/foo.git@123456 ; python_version < "3.7" + expected = f"""\ +foo @ git+https://github.com/foo/foo.git@123456 ; {MARKER_PY27.union(MARKER_PY36_ONLY)} """ - assert expected == content + assert content == expected def test_exporter_can_export_requirements_txt_with_directory_packages( - tmp_dir, poetry, working_directory + tmp_dir: str, poetry: Poetry, working_directory: Path ): poetry.locker.mock_lock_data( { @@ -1056,23 +1153,20 @@ def test_exporter_can_export_requirements_txt_with_directory_packages( set_package_requires(poetry) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -foo @ {}/tests/fixtures/sample_project -""".format( - working_directory.as_uri() - ) + expected = f"""\ +foo @ {working_directory.as_uri()}/tests/fixtures/sample_project ; {MARKER_PY} +""" - assert expected == content + assert content == expected def test_exporter_can_export_requirements_txt_with_nested_directory_packages( - tmp_dir, poetry, working_directory + tmp_dir: str, poetry: Poetry, working_directory: Path ): poetry.locker.mock_lock_data( { @@ -1097,7 +1191,10 @@ def test_exporter_can_export_requirements_txt_with_nested_directory_packages( "python-versions": "*", "source": { "type": "directory", - "url": "tests/fixtures/sample_project/../project_with_nested_local/bar", + "url": ( + "tests/fixtures/sample_project/" + "../project_with_nested_local/bar" + ), "reference": "", }, }, @@ -1109,7 +1206,10 @@ def test_exporter_can_export_requirements_txt_with_nested_directory_packages( "python-versions": "*", "source": { "type": "directory", - "url": "tests/fixtures/sample_project/../project_with_nested_local/bar/..", + "url": ( + "tests/fixtures/sample_project/" + "../project_with_nested_local/bar/.." + ), "reference": "", }, }, @@ -1124,27 +1224,23 @@ def test_exporter_can_export_requirements_txt_with_nested_directory_packages( set_package_requires(poetry) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -bar @ {}/tests/fixtures/project_with_nested_local/bar -baz @ {}/tests/fixtures/project_with_nested_local -foo @ {}/tests/fixtures/sample_project -""".format( - working_directory.as_uri(), - working_directory.as_uri(), - working_directory.as_uri(), - ) + root_uri = f"{working_directory.as_uri()}/tests/fixtures" + expected = f"""\ +bar @ {root_uri}/project_with_nested_local/bar ; {MARKER_PY} +baz @ {root_uri}/project_with_nested_local ; {MARKER_PY} +foo @ {root_uri}/sample_project ; {MARKER_PY} +""" - assert expected == content + assert content == expected def test_exporter_can_export_requirements_txt_with_directory_packages_and_markers( - tmp_dir, poetry, working_directory + tmp_dir: str, poetry: Poetry, working_directory: Path ): poetry.locker.mock_lock_data( { @@ -1173,23 +1269,21 @@ def test_exporter_can_export_requirements_txt_with_directory_packages_and_marker set_package_requires(poetry) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -foo @ {}/tests/fixtures/sample_project ; python_version < "3.7" -""".format( - working_directory.as_uri() - ) + expected = f"""\ +foo @ {working_directory.as_uri()}/tests/fixtures/sample_project ;\ + {MARKER_PY27.union(MARKER_PY36_ONLY)} +""" - assert expected == content + assert content == expected def test_exporter_can_export_requirements_txt_with_file_packages( - tmp_dir, poetry, working_directory + tmp_dir: str, poetry: Poetry, working_directory: Path ): poetry.locker.mock_lock_data( { @@ -1217,23 +1311,21 @@ def test_exporter_can_export_requirements_txt_with_file_packages( set_package_requires(poetry) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -foo @ {}/tests/fixtures/distributions/demo-0.1.0.tar.gz -""".format( - working_directory.as_uri() - ) + expected = f"""\ +foo @ {working_directory.as_uri()}/tests/fixtures/distributions/demo-0.1.0.tar.gz ;\ + {MARKER_PY} +""" - assert expected == content + assert content == expected def test_exporter_can_export_requirements_txt_with_file_packages_and_markers( - tmp_dir, poetry, working_directory + tmp_dir: str, poetry: Poetry, working_directory: Path ): poetry.locker.mock_lock_data( { @@ -1262,22 +1354,22 @@ def test_exporter_can_export_requirements_txt_with_file_packages_and_markers( set_package_requires(poetry) exporter = Exporter(poetry) - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ -foo @ {}/tests/fixtures/distributions/demo-0.1.0.tar.gz ; python_version < "3.7" -""".format( - working_directory.as_uri() - ) + uri = f"{working_directory.as_uri()}/tests/fixtures/distributions/demo-0.1.0.tar.gz" + expected = f"""\ +foo @ {uri} ; {MARKER_PY27.union(MARKER_PY36_ONLY)} +""" - assert expected == content + assert content == expected -def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, poetry): +def test_exporter_exports_requirements_txt_with_legacy_packages( + tmp_dir: str, poetry: Poetry +): poetry.pool.add_repository( LegacyRepository( "custom", @@ -1297,7 +1389,7 @@ def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, poetry) { "name": "bar", "version": "4.5.6", - "category": "main", + "category": "dev", "optional": False, "python-versions": "*", "source": { @@ -1317,26 +1409,82 @@ def test_exporter_exports_requirements_txt_with_legacy_packages(tmp_dir, poetry) set_package_requires(poetry) exporter = Exporter(poetry) - - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") + exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True) with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ + expected = f"""\ --extra-index-url https://example.com/simple -bar==4.5.6 \\ +bar==4.5.6 ; {MARKER_PY} \\ + --hash=sha256:67890 +foo==1.2.3 ; {MARKER_PY} \\ + --hash=sha256:12345 +""" + + assert content == expected + + +def test_exporter_exports_requirements_txt_with_url_false(tmp_dir: str, poetry: Poetry): + poetry.pool.add_repository( + LegacyRepository( + "custom", + "https://example.com/simple", + ) + ) + poetry.locker.mock_lock_data( + { + "package": [ + { + "name": "foo", + "version": "1.2.3", + "category": "main", + "optional": False, + "python-versions": "*", + }, + { + "name": "bar", + "version": "4.5.6", + "category": "dev", + "optional": False, + "python-versions": "*", + "source": { + "type": "legacy", + "url": "https://example.com/simple", + "reference": "", + }, + }, + ], + "metadata": { + "python-versions": "*", + "content-hash": "123456789", + "hashes": {"foo": ["12345"], "bar": ["67890"]}, + }, + } + ) + set_package_requires(poetry) + + exporter = Exporter(poetry) + exporter.export( + "requirements.txt", Path(tmp_dir), "requirements.txt", dev=True, with_urls=False + ) + + with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: + content = f.read() + + expected = f"""\ +bar==4.5.6 ; {MARKER_PY} \\ --hash=sha256:67890 -foo==1.2.3 \\ +foo==1.2.3 ; {MARKER_PY} \\ --hash=sha256:12345 """ - assert expected == content + assert content == expected def test_exporter_exports_requirements_txt_with_legacy_packages_trusted_host( - tmp_dir, poetry + tmp_dir: str, poetry: Poetry ): poetry.pool.add_repository( LegacyRepository( @@ -1350,7 +1498,7 @@ def test_exporter_exports_requirements_txt_with_legacy_packages_trusted_host( { "name": "bar", "version": "4.5.6", - "category": "main", + "category": "dev", "optional": False, "python-versions": "*", "source": { @@ -1369,32 +1517,44 @@ def test_exporter_exports_requirements_txt_with_legacy_packages_trusted_host( ) set_package_requires(poetry) exporter = Exporter(poetry) - - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") + exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True) with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ + expected = f"""\ --trusted-host example.com --extra-index-url http://example.com/simple -bar==4.5.6 \\ +bar==4.5.6 ; {MARKER_PY} \\ --hash=sha256:67890 """ - assert expected == content + assert content == expected @pytest.mark.parametrize( - ("dev", "expected"), + ["dev", "expected"], [ - (True, ["bar==1.2.2", "baz==1.2.3", "foo==1.2.1"]), - (False, ["bar==1.2.2", "foo==1.2.1"]), + ( + True, + [ + f"bar==1.2.2 ; {MARKER_PY}", + f"baz==1.2.3 ; {MARKER_PY}", + f"foo==1.2.1 ; {MARKER_PY}", + ], + ), + ( + False, + [ + f"bar==1.2.2 ; {MARKER_PY}", + f"foo==1.2.1 ; {MARKER_PY}", + ], + ), ], ) def test_exporter_exports_requirements_txt_with_dev_extras( - tmp_dir, poetry, dev, expected + tmp_dir: str, poetry: Poetry, dev: bool, expected: list[str] ): poetry.locker.mock_lock_data( { @@ -1439,19 +1599,16 @@ def test_exporter_exports_requirements_txt_with_dev_extras( set_package_requires(poetry) exporter = Exporter(poetry) - if dev: - exporter.with_groups(["dev"]) - - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") + exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=dev) with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - assert content == "{}\n".format("\n".join(expected)) + assert content == "\n".join(expected) + "\n" def test_exporter_exports_requirements_txt_with_legacy_packages_and_duplicate_sources( - tmp_dir, poetry + tmp_dir: str, poetry: Poetry ): poetry.pool.add_repository( LegacyRepository( @@ -1515,30 +1672,28 @@ def test_exporter_exports_requirements_txt_with_legacy_packages_and_duplicate_so set_package_requires(poetry) exporter = Exporter(poetry) - exporter.with_groups(["dev"]) - - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") + exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt", dev=True) with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ + expected = f"""\ --extra-index-url https://example.com/simple --extra-index-url https://foobaz.com/simple -bar==4.5.6 \\ +bar==4.5.6 ; {MARKER_PY} \\ --hash=sha256:67890 -baz==7.8.9 \\ +baz==7.8.9 ; {MARKER_PY} \\ --hash=sha256:24680 -foo==1.2.3 \\ +foo==1.2.3 ; {MARKER_PY} \\ --hash=sha256:12345 """ - assert expected == content + assert content == expected def test_exporter_exports_requirements_txt_with_legacy_packages_and_credentials( - tmp_dir, poetry, config + tmp_dir: str, poetry: Poetry, config: Config ): poetry.config.merge( { @@ -1582,27 +1737,32 @@ def test_exporter_exports_requirements_txt_with_legacy_packages_and_credentials( set_package_requires(poetry) exporter = Exporter(poetry) - exporter.with_credentials() - exporter.with_groups(["dev"]) - - exporter.export("requirements.txt", Path(tmp_dir), "requirements.txt") + exporter.export( + "requirements.txt", + Path(tmp_dir), + "requirements.txt", + dev=True, + with_credentials=True, + ) with (Path(tmp_dir) / "requirements.txt").open(encoding="utf-8") as f: content = f.read() - expected = """\ + expected = f"""\ --extra-index-url https://foo:bar@example.com/simple -bar==4.5.6 \\ +bar==4.5.6 ; {MARKER_PY} \\ --hash=sha256:67890 -foo==1.2.3 \\ +foo==1.2.3 ; {MARKER_PY} \\ --hash=sha256:12345 """ - assert expected == content + assert content == expected -def test_exporter_exports_requirements_txt_to_standard_output(tmp_dir, poetry, capsys): +def test_exporter_exports_requirements_txt_to_standard_output( + tmp_dir: str, poetry: Poetry, capsys: CaptureFixture +): poetry.locker.mock_lock_data( { "package": [ @@ -1631,13 +1791,242 @@ def test_exporter_exports_requirements_txt_to_standard_output(tmp_dir, poetry, c set_package_requires(poetry) exporter = Exporter(poetry) + exporter.export("requirements.txt", Path(tmp_dir), sys.stdout) + + out, err = capsys.readouterr() + expected = f"""\ +bar==4.5.6 ; {MARKER_PY} +foo==1.2.3 ; {MARKER_PY} +""" + + assert out == expected + + +def test_exporter_doesnt_confuse_repeated_packages( + tmp_dir: str, poetry: Poetry, capsys: CaptureFixture +): + # Testcase derived from . + poetry.locker.mock_lock_data( + { + "package": [ + { + "name": "celery", + "version": "5.1.2", + "category": "main", + "optional": False, + "python-versions": "<3.7", + "dependencies": { + "click": ">=7.0,<8.0", + "click-didyoumean": ">=0.0.3", + "click-plugins": ">=1.1.1", + }, + }, + { + "name": "celery", + "version": "5.2.3", + "category": "main", + "optional": False, + "python-versions": ">=3.7", + "dependencies": { + "click": ">=8.0.3,<9.0", + "click-didyoumean": ">=0.0.3", + "click-plugins": ">=1.1.1", + }, + }, + { + "name": "click", + "version": "7.1.2", + "category": "main", + "optional": False, + "python-versions": ( + ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + ), + }, + { + "name": "click", + "version": "8.0.3", + "category": "main", + "optional": False, + "python-versions": ">=3.6", + "dependencies": {}, + }, + { + "name": "click-didyoumean", + "version": "0.0.3", + "category": "main", + "optional": False, + "python-versions": "*", + "dependencies": {"click": "*"}, + }, + { + "name": "click-didyoumean", + "version": "0.3.0", + "category": "main", + "optional": False, + "python-versions": ">=3.6.2,<4.0.0", + "dependencies": {"click": ">=7"}, + }, + { + "name": "click-plugins", + "version": "1.1.1", + "category": "main", + "optional": False, + "python-versions": "*", + "dependencies": {"click": ">=4.0"}, + }, + ], + "metadata": { + "lock-version": "1.1", + "python-versions": "^3.6", + "content-hash": ( + "832b13a88e5020c27cbcd95faa577bf0dbf054a65c023b45dc9442b640d414e6" + ), + "hashes": { + "celery": [], + "click-didyoumean": [], + "click-plugins": [], + "click": [], + }, + }, + } + ) + root = poetry.package.with_dependency_groups([], only=True) + root.python_versions = "^3.6" + root.add_dependency( + Factory.create_dependency( + name="celery", constraint={"version": "5.1.2", "python": "<3.7"} + ) + ) + root.add_dependency( + Factory.create_dependency( + name="celery", constraint={"version": "5.2.3", "python": ">=3.7"} + ) + ) + poetry._package = root + + exporter = Exporter(poetry) + exporter.export("requirements.txt", Path(tmp_dir), sys.stdout) + + out, err = capsys.readouterr() + expected = f"""\ +celery==5.1.2 ; {MARKER_PY36_ONLY} +celery==5.2.3 ; {MARKER_PY37} +click-didyoumean==0.0.3 ; {MARKER_PY36_ONLY} +click-didyoumean==0.3.0 ; {MARKER_PY37_PY400} +click-plugins==1.1.1 ; {MARKER_PY36_ONLY.union(MARKER_PY37)} +click==7.1.2 ; {MARKER_PY36_ONLY} +click==8.0.3 ; {MARKER_PY37.union(MARKER_PY37_PY400)} +""" + assert out == expected + + +def test_exporter_handles_extras_next_to_non_extras( + tmp_dir: str, poetry: Poetry, capsys: CaptureFixture +): + # Testcase similar to the solver testcase added at #5305. + poetry.locker.mock_lock_data( + { + "package": [ + { + "name": "localstack", + "python-versions": "*", + "version": "1.0.0", + "category": "main", + "optional": False, + "dependencies": { + "localstack-ext": [ + {"version": ">=1.0.0"}, + { + "version": ">=1.0.0", + "extras": ["bar"], + "markers": 'extra == "foo"', + }, + ] + }, + "extras": {"foo": ["localstack-ext (>=1.0.0)"]}, + }, + { + "name": "localstack-ext", + "python-versions": "*", + "version": "1.0.0", + "category": "main", + "optional": False, + "dependencies": { + "something": "*", + "something-else": { + "version": ">=1.0.0", + "markers": 'extra == "bar"', + }, + "another-thing": { + "version": ">=1.0.0", + "markers": 'extra == "baz"', + }, + }, + "extras": { + "bar": ["something-else (>=1.0.0)"], + "baz": ["another-thing (>=1.0.0)"], + }, + }, + { + "name": "something", + "python-versions": "*", + "version": "1.0.0", + "category": "main", + "optional": False, + "dependencies": {}, + }, + { + "name": "something-else", + "python-versions": "*", + "version": "1.0.0", + "category": "main", + "optional": False, + "dependencies": {}, + }, + { + "name": "another-thing", + "python-versions": "*", + "version": "1.0.0", + "category": "main", + "optional": False, + "dependencies": {}, + }, + ], + "metadata": { + "lock-version": "1.1", + "python-versions": "^3.6", + "content-hash": ( + "832b13a88e5020c27cbcd95faa577bf0dbf054a65c023b45dc9442b640d414e6" + ), + "hashes": { + "localstack": [], + "localstack-ext": [], + "something": [], + "something-else": [], + "another-thing": [], + }, + }, + } + ) + root = poetry.package.with_dependency_groups([], only=True) + root.python_versions = "^3.6" + root.add_dependency( + Factory.create_dependency( + name="localstack", constraint={"version": "^1.0.0", "extras": ["foo"]} + ) + ) + poetry._package = root + + exporter = Exporter(poetry) exporter.export("requirements.txt", Path(tmp_dir), sys.stdout) out, err = capsys.readouterr() - expected = """\ -bar==4.5.6 -foo==1.2.3 + expected = f"""\ +localstack-ext==1.0.0 ; {MARKER_PY36} +localstack==1.0.0 ; {MARKER_PY36} +something-else==1.0.0 ; {MARKER_PY36} +something==1.0.0 ; {MARKER_PY36} """ assert out == expected diff --git a/tests/types.py b/tests/types.py new file mode 100644 index 0000000..e474d99 --- /dev/null +++ b/tests/types.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING +from typing import Protocol + +from cleo.testers.command_tester import CommandTester + + +if TYPE_CHECKING: + from pathlib import Path + + from poetry.installation import Installer + from poetry.installation.executor import Executor + from poetry.poetry import Poetry + from poetry.utils.env import Env + + +class CommandTesterFactory(Protocol[CommandTester]): + def __call__( + self: CommandTester, + command: str, + poetry: Poetry | None = None, + installer: Installer | None = None, + executor: Executor | None = None, + environment: Env | None = None, + ) -> CommandTester: + ... + + +class ProjectFactory(Protocol): + def __call__( + self, + name: str | None = None, + dependencies: dict[str, str] | None = None, + dev_dependencies: dict[str, str] | None = None, + pyproject_content: str | None = None, + poetry_lock_content: str | None = None, + install_deps: bool = True, + ) -> Poetry: + ... + + +class FixtureDirGetter(Protocol): + def __call__(self, name: str) -> Path: + ...