├── .github
├── dependabot.yaml
├── semantic_release
│ ├── package-lock.json
│ └── package.json
└── workflows
│ ├── lint.yaml
│ ├── matchers
│ ├── flake8.json
│ ├── mypy.json
│ └── python.json
│ ├── publish.yaml
│ ├── release.yaml
│ └── tests.yaml
├── .gitignore
├── .pre-commit-config.yaml
├── .releaserc.json
├── LICENSE
├── README.md
├── docs
├── cli.md
├── cli_usage.md
├── contributing.md
├── examples.md
├── gen_pages.py
├── logo.png
├── notes.md
└── upgrading.md
├── hatch_pip_compile
├── __about__.py
├── __init__.py
├── __main__.py
├── base.py
├── cli.py
├── exceptions.py
├── hooks.py
├── installer.py
├── lock.py
├── plugin.py
├── py.typed
└── resolver.py
├── mkdocs.yaml
├── pyproject.toml
├── requirements.txt
├── requirements
├── requirements-docs.txt
├── requirements-lint.txt
├── requirements-matrix.py3.10.txt
├── requirements-matrix.py3.11.txt
├── requirements-matrix.py3.12.txt
├── requirements-matrix.py3.8.txt
├── requirements-matrix.py3.9.txt
├── requirements-test.txt
├── requirements-versions.1.10.x.txt
├── requirements-versions.1.11.x.txt
├── requirements-versions.1.12.x.txt
├── requirements-versions.1.7.x.txt
├── requirements-versions.1.8.x.txt
└── requirements-versions.1.9.x.txt
└── tests
├── __init__.py
├── conftest.py
├── data
├── README.md
├── hatch_pip_compile_test.py
├── pyproject.toml
├── requirements.txt
└── requirements
│ ├── requirements-lint.txt
│ └── requirements-test.txt
├── test_cli.py
├── test_installer.py
├── test_integration_cli.py
├── test_lock.py
└── test_plugin.py
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: github-actions
4 | directory: /
5 | schedule:
6 | interval: monthly
7 | - package-ecosystem: pip
8 | directory: /.github/workflows
9 | schedule:
10 | interval: monthly
11 | - package-ecosystem: pip
12 | directory: /docs
13 | schedule:
14 | interval: monthly
15 | - package-ecosystem: pip
16 | directory: /
17 | schedule:
18 | interval: monthly
19 | versioning-strategy: lockfile-only
20 | allow:
21 | - dependency-type: all
22 |
--------------------------------------------------------------------------------
/.github/semantic_release/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "@semantic-release/exec": "^6.0.3",
4 | "@semantic-release/git": "^10.0.1",
5 | "@semantic-release/github": "^8.0.7",
6 | "semantic-release": "^21.0.1",
7 | "semantic-release-gitmoji": "^1.6.4"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yaml:
--------------------------------------------------------------------------------
1 | name: Lint
2 |
3 | on:
4 | pull_request:
5 | branches: ["**"]
6 |
7 | jobs:
8 | lint:
9 | runs-on: ubuntu-latest
10 | env:
11 | PIP_COMPILE_DISABLE: true
12 | HATCH_DEBUG: true
13 | steps:
14 | - name: Set up Github Workspace
15 | uses: actions/checkout@v4
16 | with:
17 | fetch-depth: 0
18 | - name: Set up Python Environment
19 | uses: actions/setup-python@v5
20 | with:
21 | python-version: "3.11"
22 | - name: Install Hatch
23 | run: |
24 | python -m pip install --upgrade pip wheel
25 | python -m pip install -q hatch pre-commit
26 | python -m pip install -q "${{ github.workspace }}"
27 | hatch --version
28 | - name: Lint
29 | id: lint
30 | continue-on-error: true
31 | run: |
32 | echo "::add-matcher::.github/workflows/matchers/flake8.json"
33 | hatch run lint:style
34 | echo "::remove-matcher owner=flake8::"
35 | - name: Type Checking
36 | id: check
37 | continue-on-error: true
38 | run: |
39 | echo "::add-matcher::.github/workflows/matchers/mypy.json"
40 | hatch run lint:typing
41 | echo "::remove-matcher owner=mypy::"
42 | - name: Raise Errors For Failures
43 | if: |
44 | steps.lint.outcome != 'success' ||
45 | steps.check.outcome != 'success'
46 | run: |
47 | echo "Lint: ${{ steps.lint.outcome }}"
48 | echo "Check: ${{ steps.check.outcome }}"
49 | exit 1
50 |
--------------------------------------------------------------------------------
/.github/workflows/matchers/flake8.json:
--------------------------------------------------------------------------------
1 | {
2 | "problemMatcher": [
3 | {
4 | "owner": "flake8",
5 | "pattern": [
6 | {
7 | "regexp": "^(.*?):(\\d+):(\\d+): (.*)$",
8 | "file": 1,
9 | "line": 2,
10 | "column": 3,
11 | "message": 4
12 | }
13 | ]
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/.github/workflows/matchers/mypy.json:
--------------------------------------------------------------------------------
1 | {
2 | "problemMatcher": [
3 | {
4 | "owner": "mypy",
5 | "pattern": [
6 | {
7 | "regexp": "^(.+):(\\d+):\\s(error|warning|note):\\s(.+)$",
8 | "file": 1,
9 | "line": 2,
10 | "severity": 3,
11 | "message": 4
12 | }
13 | ]
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/.github/workflows/matchers/python.json:
--------------------------------------------------------------------------------
1 | {
2 | "problemMatcher": [
3 | {
4 | "owner": "python",
5 | "pattern": [
6 | {
7 | "regexp": "^\\s*File\\s\\\"(.*)\\\",\\sline\\s(\\d+),\\sin\\s(.*)$",
8 | "file": 1,
9 | "line": 2
10 | },
11 | {
12 | "regexp": "^\\s*raise\\s(.*)\\(\\'(.*)\\'\\)$",
13 | "message": 2
14 | }
15 | ]
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yaml:
--------------------------------------------------------------------------------
1 | name: Publishing
2 |
3 | on:
4 | release:
5 | types:
6 | - published
7 |
8 | jobs:
9 | pypi-publish:
10 | name: PyPI
11 | if: github.repository_owner == 'juftin'
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Check out the repository
15 | uses: actions/checkout@v4
16 | with:
17 | fetch-depth: 2
18 | - name: Set up Python
19 | uses: actions/setup-python@v5
20 | with:
21 | python-version: "3.11"
22 | - name: Install Hatch
23 | run: |
24 | python -m pip install --upgrade pip wheel
25 | python -m pip install -q hatch pre-commit
26 | python -m pip install -q "${{ github.workspace }}"
27 | hatch --version
28 | - name: Build package
29 | run: |
30 | hatch build
31 | - name: Publish package on PyPI
32 | uses: pypa/gh-action-pypi-publish@release/v1
33 | with:
34 | user: __token__
35 | password: ${{ secrets.PYPI_TOKEN }}
36 |
--------------------------------------------------------------------------------
/.github/workflows/release.yaml:
--------------------------------------------------------------------------------
1 | name: Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | release:
10 | name: github-release
11 | if: github.repository_owner == 'juftin'
12 | runs-on: ubuntu-latest
13 | permissions:
14 | contents: write
15 | issues: write
16 | pull-requests: write
17 | steps:
18 | - name: Check out the repository
19 | uses: actions/checkout@v4
20 | with:
21 | fetch-depth: 2
22 | ref: main
23 | - name: Setup Node.js
24 | uses: actions/setup-node@v4
25 | - name: Set up Python
26 | uses: actions/setup-python@v5
27 | with:
28 | python-version: "3.11"
29 | - name: Install Hatch
30 | run: |
31 | python -m pip install --upgrade pip wheel
32 | python -m pip install -q hatch pre-commit
33 | python -m pip install -q "${{ github.workspace }}"
34 | hatch --version
35 | - name: Release
36 | run: hatch run gen:release
37 | env:
38 | GITHUB_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
39 | GIT_AUTHOR_NAME: github-actions[bot]
40 | GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
41 | GIT_COMMITTER_NAME: github-actions[bot]
42 | GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
43 |
44 | github-pages-publish:
45 | runs-on: ubuntu-latest
46 | needs: release
47 | if: github.ref == 'refs/heads/main' && github.repository_owner == 'juftin'
48 | permissions:
49 | pages: write
50 | id-token: write
51 | environment:
52 | name: github-pages
53 | url: ${{ steps.deployment.outputs.page_url }}
54 | steps:
55 | - name: Checkout Latest Changes
56 | uses: actions/checkout@v4
57 | with:
58 | ref: ${{ github.ref }}
59 | fetch-depth: 0
60 | - name: Set up Python Environment
61 | uses: actions/setup-python@v5
62 | with:
63 | python-version: "3.11"
64 | - name: Install Hatch
65 | run: |
66 | python -m pip install --upgrade pip wheel
67 | python -m pip install -q hatch pre-commit
68 | python -m pip install -q "${{ github.workspace }}"
69 | hatch --version
70 | - name: Create Virtual Environment
71 | run: hatch env create docs
72 | - name: Build Site
73 | run: hatch run docs:build
74 | - name: Setup GitHub Pages
75 | uses: actions/configure-pages@v4
76 | - name: Upload Artifact
77 | uses: actions/upload-pages-artifact@v3
78 | with:
79 | path: site/
80 | - name: Deploy to GitHub Pages
81 | id: deployment
82 | uses: actions/deploy-pages@v4
83 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yaml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | paths:
8 | - hatch_pip_compile/**
9 | - pyproject.toml
10 | - .github/workflows/tests.yaml
11 | - tests/**
12 | pull_request:
13 | branches: ["**"]
14 | paths:
15 | - hatch_pip_compile/**
16 | - pyproject.toml
17 | - .github/workflows/tests.yaml
18 | - tests/**
19 | schedule:
20 | - cron: 0 12 1 * *
21 | jobs:
22 | test-suite:
23 | strategy:
24 | fail-fast: false
25 | matrix:
26 | include:
27 | - {
28 | name: Python-3.12,
29 | python: "3.12",
30 | command: "matrix:cov",
31 | matrix: "+py=3.12",
32 | hatch_version: "1.0",
33 | os: ubuntu-latest,
34 | }
35 | - {
36 | name: Python-3.11,
37 | python: "3.11",
38 | command: "matrix:cov",
39 | matrix: "+py=3.11",
40 | hatch_version: "1.0",
41 | os: ubuntu-latest,
42 | }
43 | - {
44 | name: Python-3.10,
45 | python: "3.10",
46 | command: "matrix:cov",
47 | matrix: "+py=3.10",
48 | hatch_version: "1.0",
49 | os: ubuntu-latest,
50 | }
51 | - {
52 | name: Python-3.9,
53 | python: "3.9",
54 | command: "matrix:cov",
55 | matrix: "+py=3.9",
56 | hatch_version: "1.0",
57 | os: ubuntu-latest,
58 | }
59 | - {
60 | name: Python-3.8,
61 | python: "3.8",
62 | command: "matrix:cov",
63 | matrix: "+py=3.8",
64 | hatch_version: "1.0",
65 | os: ubuntu-latest,
66 | }
67 | - {
68 | name: Hatch-1.7.x,
69 | python: "3.11",
70 | command: "versions:cov",
71 | matrix: "+version=1.7.x",
72 | hatch_version: "1.7.0",
73 | os: ubuntu-latest,
74 | }
75 | - {
76 | name: Hatch-1.8.x,
77 | python: "3.11",
78 | command: "versions:cov",
79 | matrix: "+version=1.8.x",
80 | hatch_version: "1.8.1",
81 | os: ubuntu-latest,
82 | }
83 | - {
84 | name: Hatch-1.9.x,
85 | python: "3.11",
86 | command: "versions:cov",
87 | matrix: "+version=1.9.x",
88 | hatch_version: "1.9.7",
89 | os: ubuntu-latest,
90 | }
91 | - {
92 | name: Hatch-1.10.x,
93 | python: "3.11",
94 | command: "versions:cov",
95 | matrix: "+version=1.10.x",
96 | hatch_version: "1.10.0",
97 | os: ubuntu-latest,
98 | }
99 | - {
100 | name: Hatch-1.11.x,
101 | python: "3.11",
102 | command: "versions:cov",
103 | matrix: "+version=1.11.x",
104 | hatch_version: "1.11.1",
105 | os: ubuntu-latest,
106 | }
107 | - {
108 | name: Hatch-1.12.x,
109 | python: "3.11",
110 | command: "versions:cov",
111 | matrix: "+version=1.12.x",
112 | hatch_version: "1.12.0",
113 | os: ubuntu-latest,
114 | }
115 | - {
116 | name: Hatch-Windows,
117 | python: "3.11",
118 | command: "matrix:cov",
119 | matrix: "+py=3.11",
120 | hatch_version: "1.0",
121 | os: windows-latest,
122 | }
123 | runs-on: ${{ matrix.os }}
124 | concurrency:
125 | group: ${{ github.workflow }}-${{ matrix.name }}-${{ github.ref }}
126 | cancel-in-progress: true
127 | env:
128 | PIP_COMPILE_DISABLE: true
129 | HATCH_DEBUG: true
130 | steps:
131 | - name: Set up Github Workspace
132 | uses: actions/checkout@v4
133 | with:
134 | fetch-depth: 0
135 | - name: Set up Python Environment ${{ matrix.python }}
136 | uses: actions/setup-python@v5
137 | with:
138 | python-version: ${{ matrix.python }}
139 | - name: Install Default Python
140 | if: matrix.python != '3.11'
141 | uses: actions/setup-python@v5
142 | with:
143 | python-version: "3.11"
144 | - name: Install Hatch
145 | run: |
146 | python -m pip install --upgrade pip wheel
147 | python -m pip install -q "hatch~=${{ matrix.hatch_version }}"
148 | python -m pip install -q pre-commit
149 | python -m pip install -q "${{ github.workspace }}"
150 | hatch --version
151 | - name: Test Suite
152 | run: |
153 | echo "::add-matcher::.github/workflows/matchers/python.json"
154 | hatch run ${{ matrix.matrix }} ${{ matrix.command }}
155 | echo "::remove-matcher owner=python::"
156 | - name: Upload coverage reports to Codecov
157 | if: matrix.os == 'ubuntu-latest' && matrix.python == '3.11' && matrix.command == 'matrix:cov'
158 | uses: codecov/codecov-action@v3
159 | env:
160 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
161 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 | docs/source/api
74 | docs/source/README.md
75 |
76 | # PyBuilder
77 | target/
78 |
79 | # Jupyter Notebook
80 | .ipynb_checkpoints
81 |
82 | # IPython
83 | profile_default/
84 | ipython_config.py
85 |
86 | # pyenv
87 | .python-version
88 |
89 | # pipenv
90 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
91 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
92 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
93 | # install all needed dependencies.
94 | #Pipfile.lock
95 |
96 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
97 | __pypackages__/
98 |
99 | # Celery stuff
100 | celerybeat-schedule
101 | celerybeat.pid
102 |
103 | # SageMath parsed files
104 | *.sage.py
105 |
106 | # Environments
107 | .env
108 | .venv
109 | env/
110 | venv/
111 | ENV/
112 | env.bak/
113 | venv.bak/
114 |
115 | # Spyder project settings
116 | .spyderproject
117 | .spyproject
118 |
119 | # Rope project settings
120 | .ropeproject
121 |
122 | # documentation
123 | /site
124 | docs/source/_autosummary
125 |
126 | # mypy
127 | .mypy_cache/
128 | .dmypy.json
129 | dmypy.json
130 |
131 | # Mac Files
132 | .DS_Store
133 |
134 | # IDE Files
135 | .idea/
136 |
137 | # Node.js
138 | node_modules/
139 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | default_stages: [commit]
2 | fail_fast: false
3 |
4 | repos:
5 | - repo: https://github.com/pre-commit/pre-commit-hooks
6 | rev: v4.5.0
7 | hooks:
8 | - id: trailing-whitespace
9 | - id: end-of-file-fixer
10 | - id: check-yaml
11 | exclude: mkdocs.yaml
12 | - id: check-ast
13 | - id: check-docstring-first
14 | - id: check-merge-conflict
15 | - id: mixed-line-ending
16 |
17 | - repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
18 | rev: v2.11.0
19 | hooks:
20 | - id: pretty-format-toml
21 | args: [--autofix]
22 |
23 | - repo: https://github.com/pre-commit/mirrors-prettier
24 | rev: v3.0.3
25 | hooks:
26 | - id: prettier
27 | args: [--print-width=88, --tab-width=4]
28 | exclude: |
29 | (?x)(
30 | .github/semantic_release/release_notes.hbs |
31 | docs/cli.md
32 | )
33 | additional_dependencies:
34 | - prettier
35 |
36 | - repo: local
37 | hooks:
38 | - id: format
39 | name: format
40 | description: Runs Code Auto-Formatters
41 | entry: hatch run lint:fmt
42 | language: system
43 | pass_filenames: false
44 | - id: lint
45 | name: lint
46 | description: Runs Code Linters
47 | entry: hatch run lint:all
48 | language: system
49 | pass_filenames: false
50 | require_serial: false
51 |
--------------------------------------------------------------------------------
/.releaserc.json:
--------------------------------------------------------------------------------
1 | {
2 | "branches": [
3 | "main",
4 | "master",
5 | "next",
6 | "next-major",
7 | "+([0-9])?(.{+([0-9]),x}).x",
8 | {
9 | "name": "beta",
10 | "prerelease": true
11 | },
12 | {
13 | "name": "alpha",
14 | "prerelease": true
15 | }
16 | ],
17 | "plugins": [
18 | "semantic-release-gitmoji",
19 | [
20 | "@semantic-release/exec",
21 | {
22 | "prepareCmd": "hatch version ${nextRelease.version} && hatch build"
23 | }
24 | ],
25 | [
26 | "@semantic-release/git",
27 | {
28 | "assets": ["pyproject.toml", "*/__about__.py"],
29 | "message": "🔖 hatch-pip-compile ${nextRelease.version}\n\n${nextRelease.notes}\n[skip ci]"
30 | }
31 | ],
32 | [
33 | "@semantic-release/github",
34 | {
35 | "assets": [
36 | {
37 | "path": "dist/*.whl"
38 | },
39 | {
40 | "path": "dist/*.tar.gz"
41 | }
42 | ]
43 | }
44 | ]
45 | ]
46 | }
47 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright © 2023 Justin Flannery
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
hatch-pip-compile
2 |
3 |
8 |
9 |
10 | hatch plugin to use pip-compile (or uv) to manage project dependencies and lockfiles.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | ## Usage
30 |
31 | The `hatch-pip-compile` plugin will automatically run `pip-compile` whenever your
32 | environment needs to be updated. Behind the scenes, this plugin creates a lockfile
33 | at `requirements.txt` (non-default lockfiles are located at
34 | `requirements/requirements-{env_name}.txt`). Once the dependencies are resolved
35 | the plugin will install the lockfile into your virtual environment and keep it
36 | up-to-date.
37 |
38 | ## Installation
39 |
40 | Declare `hatch-pip-compile` as a dependency in your `pyproject.toml` file under the
41 | `[tool.hatch.env]` table and hatch will automatically install it. You must also have
42 | your environment type set to `pip-compile` (see [Configuration](#configuration)).
43 |
44 | - **_pyproject.toml_**
45 |
46 | ```toml
47 | [tool.hatch.env]
48 | requires = [
49 | "hatch-pip-compile"
50 | ]
51 |
52 | [tool.hatch.envs.default]
53 | type = "pip-compile"
54 | ```
55 |
56 | - **_hatch.toml_**
57 |
58 | ```toml
59 | [env]
60 | requires = [
61 | "hatch-pip-compile"
62 | ]
63 |
64 | [envs.default]
65 | type = "pip-compile"
66 | ```
67 |
68 | ## Configuration
69 |
70 | Set your environment type to `pip-compile` to use this plugin for the respective environment:
71 |
72 | - **_pyproject.toml_**
73 |
74 | ```toml
75 | [tool.hatch.envs.default]
76 | type = "pip-compile"
77 | ```
78 |
79 | - **_hatch.toml_**
80 |
81 | ```toml
82 | [envs.default]
83 | type = "pip-compile"
84 | ```
85 |
86 | ### Common Scenarios
87 |
88 | - [lock-filename](docs/examples.md#lock-filename) - changing the default lockfile path
89 | - [pip-compile-constraint](docs/examples.md#pip-compile-constraint) - syncing dependency versions across environments
90 | - [Upgrading Dependencies](docs/examples.md#upgrading-dependencies) - how to upgrade dependencies
91 | - [Using Hashes](docs/examples.md#pip-compile-hashes) - how to include hashes in your lockfile
92 | - [Using uv instead of pip-compile](docs/examples.md#pip-compile-resolver) - how to use `uv` instead of `pip-compile`
93 |
94 | ### Configuration Options
95 |
96 | The plugin gives you options to configure how lockfiles are generated and how they are installed
97 | into your environment.
98 |
99 | The following example shows how to specify the `pip-compile-hashes` option
100 | on your environment in your `pyproject.toml` file:
101 |
102 | ```toml
103 | [tool.hatch.envs.default]
104 | type = "pip-compile"
105 | pip-compile-hashes = true
106 | ```
107 |
108 | #### Generating Lockfiles
109 |
110 | | name | type | description |
111 | | ----------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------- |
112 | | [lock-filename](docs/examples.md#lock-filename) | `str` | The filename of the ultimate lockfile. `default` env is `requirements.txt`, non-default is `requirements/requirements-{env_name}.txt` |
113 | | [pip-compile-constraint](docs/examples.md#pip-compile-constraint) | `str` | An environment to use as a constraint file, ensuring that all shared dependencies are pinned to the same versions. |
114 | | [pip-compile-hashes](docs/examples.md#pip-compile-hashes) | `bool` | Whether to generate hashes in the lockfile. Defaults to `false`. |
115 | | [pip-compile-resolver](docs/examples.md#pip-compile-resolver) | `str` | Whether to use `pip-compile` or `uv` to resolve dependencies into the project. Defaults to `pip-compile` |
116 | | [pip-compile-args](docs/examples.md#pip-compile-args) | `list[str]` | Additional command-line arguments to pass to `pip-compile-resolver` |
117 | | [pip-compile-verbose](docs/examples.md#pip-compile-verbose) | `bool` | Set to `true` to run `pip-compile` in verbose mode instead of quiet mode, set to `false` to silence warnings |
118 |
119 | #### Installing Lockfiles
120 |
121 | | name | type | description |
122 | | --------------------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------- |
123 | | [pip-compile-installer](docs/examples.md#pip-compile-installer) | `str` | Whether to use `pip`, `pip-sync`, or `uv` to install dependencies into the project. Defaults to `pip` |
124 | | [pip-compile-install-args](docs/examples.md#pip-compile-install-args) | `list[str]` | Additional command-line arguments to pass to `pip-compile-installer` |
125 |
126 |
127 |
128 | ---
129 |
130 | ---
131 |
132 | #### Check Out the [Docs]
133 |
134 | - [Examples 📚](docs/examples.md)
135 | - [Upgrading 🚀](docs/upgrading.md)
136 | - [Command Line Usage 📦](docs/cli_usage.md)
137 | - [Notes 📝](docs/notes.md)
138 |
139 | #### Looking to contribute? See the [Contributing Guide]
140 |
141 | #### See the [Changelog]
142 |
143 |
144 |
145 | [Docs]: https://juftin.github.io/hatch-pip-compile/
146 | [Contributing Guide]: https://juftin.github.io/hatch-pip-compile/contributing
147 | [Changelog]: https://github.com/juftin/hatch-pip-compile/releases
148 |
--------------------------------------------------------------------------------
/docs/cli.md:
--------------------------------------------------------------------------------
1 | # Command Line Interface
2 |
3 | It's recommend to use [pipx] to install the CLI, but
4 | you can also install it with [pip]:
5 |
6 | ```shell
7 | pipx install hatch-pip-compile
8 | ```
9 |
10 | ::: mkdocs-click
11 | :module: hatch_pip_compile.cli
12 | :command: cli
13 | :prog_name: hatch-pip-compile
14 | :style: table
15 | :list_subcommands: True
16 |
17 | ## How it works
18 |
19 | The `hatch-pip-compile` CLI is a wrapper around `hatch` that simply
20 | sets the `PIP_COMPILE_UPGRADE` / `PIP_COMPILE_UPGRADE_PACKAGE` environment
21 | variables before running a `hatch` command in a given environment.
22 |
23 | These environment variables are used by the `hatch-pip-compile` plugin
24 | to run the `pip-compile` command with the `--upgrade` / `--upgrade-package`
25 | flags.
26 |
27 | ## Examples
28 |
29 | ### Upgrade the `default` environment
30 |
31 | The below command will upgrade all packages in the `default` environment.
32 |
33 | ```shell
34 | hatch-pip-compile --upgrade
35 | ```
36 |
37 | ### Upgrade a non-default environment
38 |
39 | The below command will upgrade all packages in the `docs` environment.
40 |
41 | ```shell
42 | hatch-pip-compile docs --upgrade
43 | ```
44 |
45 | ### Upgrade a specific package
46 |
47 | The below command will upgrade the `requests` package in the `default`
48 | environment.
49 |
50 | ```shell
51 | hatch-pip-compile --upgrade-package requests
52 | ```
53 |
54 | ### Upgrade all `pip-compile` environments
55 |
56 | The below command will upgrade all packages in all `pip-compile` environments.
57 |
58 | ```shell
59 | hatch-pip-compile --upgrade --all
60 | ```
61 |
62 | [pipx]: https://github.com/pypa/pipx
63 | [pip]: https://pip.pypa.io
64 |
--------------------------------------------------------------------------------
/docs/cli_usage.md:
--------------------------------------------------------------------------------
1 | # Using the `hatch-pip-compile` CLI
2 |
3 | For convenience this package also makes a CLI available to handle the setting /
4 | unsetting of the `PIP_COMPILE_UPGRADE` / `PIP_COMPILE_UPGRADE_PACKAGE` environment variables
5 | and invoking the `hatch env run` command for you automatically. To use the CLI you'll need to
6 | install it outside your `pyproject.toml` / `hatch.toml` file.
7 |
8 | I recommend using [pipx] to
9 | install the CLI, but you can also install it directly with [pip]:
10 |
11 | ```shell
12 | pipx install hatch-pip-compile
13 | ```
14 |
15 | Once installed, you can run the CLI with the `hatch-pip-compile` command.
16 |
17 | ## Examples
18 |
19 | ### Upgrade the `default` environment
20 |
21 | The below command will upgrade all packages in the `default` environment.
22 |
23 | ```shell
24 | hatch-pip-compile --upgrade
25 | ```
26 |
27 | ### Upgrade a non-default environment
28 |
29 | The below command will upgrade all packages in the `docs` environment.
30 |
31 | ```shell
32 | hatch-pip-compile docs --upgrade
33 | ```
34 |
35 | ### Upgrade a specific package
36 |
37 | The below command will upgrade the `requests` package in the `default`
38 | environment.
39 |
40 | ```shell
41 | hatch-pip-compile --upgrade-package requests
42 | ```
43 |
44 | ### Upgrade all `pip-compile` environments
45 |
46 | The below command will upgrade all packages in all `pip-compile` environments.
47 |
48 | ```shell
49 | hatch-pip-compile --upgrade --all
50 | ```
51 |
52 | [pipx]: https://github.com/pypa/pipx
53 | [pip]: https://pip.pypa.io
54 |
--------------------------------------------------------------------------------
/docs/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | ## Environment Setup
4 |
5 | > TIP: **pipx**
6 | >
7 | > This documentaion uses [pipx] to
8 | > install and manage non-project command line tools like `hatch` and
9 | > `pre-commit`. If you don't already have `pipx` installed, make sure to
10 | > see their [documentation](https://pypa.github.io/pipx/installation/).
11 | > If you prefer not to use `pipx`, you can use `pip` instead.
12 |
13 | 1. Install [hatch](https://github.com/pypa/hatch)
14 |
15 | ```shell
16 | pipx install hatch
17 | ```
18 |
19 | > NOTE: **pre-commit**
20 | >
21 | > Hatch will attempt to set up pre-commit hooks for you using
22 | > [pre-commit]. If you don't already, make sure to install
23 | > pre-commit as well: `pipx install pre-commit`
24 |
25 | 2. Build the Virtual Environment
26 |
27 | ```shell
28 | hatch env create
29 | ```
30 |
31 | 3. If you need to, you can link a hatch virtual environment to your IDE.
32 | They can be located by name with the `env find` command:
33 |
34 | ```shell
35 | hatch env find default
36 | ```
37 |
38 | 4. Activate the Virtual Environment
39 |
40 | ```shell
41 | hatch shell
42 | ```
43 |
44 | ## Using Hatch
45 |
46 | ### Hatch Cheat Sheet
47 |
48 | | Command Description | Command | Notes |
49 | | -------------------------- | -------------------------- | ---------------------------------------------- |
50 | | Run Formatting | `hatch run lint:fmt` | Runs `ruff` code formatter |
51 | | Run Linting | `hatch run lint:all` | Runs `ruff` and `mypy` linters / type checkers |
52 | | Run Type Checking | `hatch run lint:typing` | Runs `mypy` type checker |
53 | | Serve the Documentation | `hatch run docs:serve` | Serve the documentation using MkDocs |
54 | | Run the `pre-commit` Hooks | `hatch run lint:precommit` | Runs the `pre-commit` hooks on all files |
55 |
56 | ### Hatch Explanation
57 |
58 | Hatch is a Python package manager. It's most basic use is as a standardized build-system.
59 | However, hatch also has some extra features which this project takes advantage of.
60 | These features include virtual environment management and the organization of common
61 | scripts like linting and testing. All the operations in hatch take place in one
62 | of its managed virtual environments.
63 |
64 | Hatch has a variety of environments, to see them simply ask hatch:
65 |
66 | ```bash exec="on" result="markdown" source="tabbed-left" tabs="hatch CLI|Output"
67 | hatch env show
68 | ```
69 |
70 | That above command will tell you that there are four environments that
71 | you can use:
72 |
73 | - `default`
74 | - `docs`
75 | - `gen`
76 | - `lint`
77 |
78 | Each of these environments has a set of commands that you can run.
79 | To see the commands for a specific environment, run:
80 |
81 | ```bash exec="on" result="markdown" source="tabbed-left" tabs="hatch CLI|Output"
82 | hatch env show default
83 | ```
84 |
85 | Here we can see that the `default` environment has the following commands:
86 |
87 | - `cov`
88 | - `cov-report`
89 | - `test`
90 | - `test-cov`
91 |
92 | The one that we're interested in is `cov`, which will run the tests
93 | for the project.
94 |
95 | ```bash
96 | hatch run cov
97 | ```
98 |
99 | Since `cov` is in the default environment, we can run it without
100 | specifying the environment. However, to run the `serve` command in the
101 | `docs` environment, we need to specify the environment:
102 |
103 | ```bash
104 | hatch run docs:serve
105 | ```
106 |
107 | You can see what scripts are available using the `env show` command
108 |
109 | ```bash exec="on" result="markdown" source="tabbed-left" tabs="hatch CLI|Output"
110 | hatch env show docs
111 | ```
112 |
113 | ## Committing Code
114 |
115 | This project uses [pre-commit] to run a set of
116 | checks on the code before it is committed. The pre-commit hooks are
117 | installed by hatch automatically when you run it for the first time.
118 |
119 | This project uses [semantic-versioning] standards, managed by [semantic-release].
120 | Releases for this project are handled entirely by CI/CD via pull requests being
121 | merged into the `main` branch. Contributions follow the [gitmoji] standards
122 | with [conventional commits].
123 |
124 | While you can denote other changes on your commit messages with [gitmoji], the following
125 | commit message emoji prefixes are the only ones to trigger new releases:
126 |
127 | | Emoji | Shortcode | Description | Semver |
128 | | ----- | ------------- | --------------------------- | ------ |
129 | | 💥 | \:boom\: | Introduce breaking changes. | Major |
130 | | ✨ | \:sparkles\: | Introduce new features. | Minor |
131 | | 🐛 | \:bug\: | Fix a bug. | Patch |
132 | | 🚑 | \:ambulance\: | Critical hotfix. | Patch |
133 | | 🔒 | \:lock\: | Fix security issues. | Patch |
134 |
135 | Most features can be squash merged into a single commit on a pull-request.
136 | When merging multiple commits, they will be summarized into a single release.
137 |
138 | If you're working on a new feature, your commit message might look like:
139 |
140 | ```text
141 | ✨ New Feature Description
142 | ```
143 |
144 | Bug fix commits would look like this:
145 |
146 | ```text
147 | 🐛 Bug Fix Description
148 | ```
149 |
150 | If you're working on a feature that introduces breaking changes, your
151 | commit message might look like:
152 |
153 | ```text
154 | 💥 Breaking Change Description
155 | ```
156 |
157 | Other commits that don't trigger a release might look like:
158 |
159 | ```text
160 | 📝 Documentation Update Description
161 | 👷 CI/CD Update Description
162 | 🧪 Testing Changes Description
163 | 🚚 Moving/Renaming Description
164 | ⬆️ Dependency Upgrade Description
165 | 🎨 Non-Material Code Tidying Description
166 | ```
167 |
168 | ### Pre-Releases
169 |
170 | [semantic-release] supports pre-releases. To trigger a pre-release, you
171 | would merge your pull request into an `alpha` or `beta` branch.
172 |
173 | ### Specific Release Versions
174 |
175 | In some cases you need more advanced control around what kind of release you
176 | need to create. If you need to release a specific version, you can do so by creating a
177 | new branch with the version number as the branch name. For example, if the
178 | current version is `2.3.2`, but you need to release a fix as `1.2.5`, you
179 | would create a branch named `1.2.x` and merge your changes into that branch.
180 |
181 | See the [semantic-release documentation] for more information about
182 | branch based releases and other advanced release cases.
183 |
184 | [pipx]: https://pipx.pypa.io
185 | [pre-commit]: https://pre-commit.com
186 | [gitmoji]: https://gitmoji.dev
187 | [conventional commits]: https://www.conventionalcommits.org
188 | [semantic-release]: https://github.com/semantic-release/semantic-release
189 | [semantic-versioning]: https://semver.org
190 | [semantic-release documentation]: https://semantic-release.gitbook.io/semantic-release/usage/configuration#branches
191 |
--------------------------------------------------------------------------------
/docs/examples.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | ## lock-filename
4 |
5 | The path (including the directory) to the ultimate lockfile. Defaults to `requirements.txt` in the project root
6 | for the `default` environment, and `requirements/requirements-{env_name}.txt` for non-default environments.
7 |
8 | Changing the lock file path:
9 |
10 | - **_pyproject.toml_**
11 |
12 | ```toml
13 | [tool.hatch.envs.]
14 | type = "pip-compile"
15 | lock-filename = "locks/{env_name}.lock"
16 | ```
17 |
18 | - **_hatch.toml_**
19 |
20 | ```toml
21 | [envs.]
22 | type = "pip-compile"
23 | lock-filename = "locks/{env_name}.lock"
24 | ```
25 |
26 | Changing the lock filename to a path in the project root:
27 |
28 | - **_pyproject.toml_**
29 |
30 | ```toml
31 | [tool.hatch.envs.lint]
32 | type = "pip-compile"
33 | lock-filename = "linting-requirements.txt"
34 | ```
35 |
36 | - **_hatch.toml_**
37 |
38 | ```toml
39 | [envs.lint]
40 | type = "pip-compile"
41 | lock-filename = "linting-requirements.txt"
42 | ```
43 |
44 | ## pip-compile-constraint
45 |
46 | An environment to use as a constraint, ensuring that all shared dependencies are
47 | pinned to the same versions. For example, if you have a `default` environment and
48 | a `test` environment, you can set the `pip-compile-constraint` option to `default`
49 | on the `test` environment to ensure that all shared dependencies are pinned to the
50 | same versions. `pip-compile-constraint` can also be set to an empty string to disable
51 | the feature.
52 |
53 | - **_pyproject.toml_**
54 |
55 | ```toml
56 | [tool.hatch.envs.default]
57 | type = "pip-compile"
58 |
59 | [tool.hatch.envs.test]
60 | dependencies = [
61 | "pytest"
62 | ]
63 | type = "pip-compile"
64 | pip-compile-constraint = "default"
65 | ```
66 |
67 | - **_hatch.toml_**
68 |
69 | ```toml
70 | [envs.default]
71 | type = "pip-compile"
72 |
73 | [envs.test]
74 | dependencies = [
75 | "pytest"
76 | ]
77 | type = "pip-compile"
78 | pip-compile-constraint = "default"
79 | ```
80 |
81 | By default, all environments inherit from the `default` environment via
82 | [inheritance]. A common use case is to set the `pip-compile-constraint`
83 | and `type` options on the `default` environment and inherit them on
84 | all other environments. It's important to note that when `detached = true`,
85 | inheritance is disabled and the `type` and `pip-compile-constraint` options
86 | must be set explicitly.
87 |
88 | - **_pyproject.toml_**
89 |
90 | ```toml
91 | [tool.hatch.envs.default]
92 | type = "pip-compile"
93 | pip-compile-constraint = "default"
94 |
95 | [tool.hatch.envs.test]
96 | dependencies = [
97 | "pytest"
98 | ]
99 | ```
100 |
101 | - **_hatch.toml_**
102 |
103 | ```toml
104 | [envs.default]
105 | type = "pip-compile"
106 | pip-compile-constraint = "default"
107 |
108 | [envs.test]
109 | dependencies = [
110 | "pytest"
111 | ]
112 | ```
113 |
114 | ## pip-compile-hashes
115 |
116 | Whether to generate hashes in the lockfile. Defaults to `false`.
117 |
118 | - **_pyproject.toml_**
119 |
120 | ```toml
121 | [tool.hatch.envs.]
122 | type = "pip-compile"
123 | pip-compile-hashes = true
124 | ```
125 |
126 | - **_hatch.toml_**
127 |
128 | ```toml
129 | [envs.]
130 | type = "pip-compile"
131 | pip-compile-hashes = true
132 | ```
133 |
134 | ## pip-compile-resolver
135 |
136 | Which resolver to use to generate the lockfile. Defaults to `pip-compile`.
137 |
138 | [uv] is a drop in replacement for `pip-compile` with a much faster resolver written in rust.
139 | If you'd like to use `uv` instead of `pip-compile` you can set the `pip-compile-resolver` option.
140 |
141 | > NOTE: **pip-compile-installer**
142 | >
143 | > [uv] can also be used as the default installer instead of `pip`. See
144 | > the [pip-compile-installer](#pip-compile-installer) option for more
145 | > information.
146 |
147 | - **_pyproject.toml_**
148 |
149 | ```toml
150 | [tool.hatch.envs.]
151 | type = "pip-compile"
152 | pip-compile-resolver = "uv"
153 | ```
154 |
155 | - **_hatch.toml_**
156 |
157 | ```toml
158 | [envs.]
159 | type = "pip-compile"
160 | pip-compile-resolver = "uv"
161 | ```
162 |
163 | ## pip-compile-args
164 |
165 | Extra arguments to pass to `pip-compile-resolver`. Custom PyPI indexes can be specified here.
166 |
167 | - **_pyproject.toml_**
168 |
169 | ```toml
170 | [tool.hatch.envs.]
171 | type = "pip-compile"
172 | pip-compile-args = [
173 | "--index-url",
174 | "https://pypi.org/simple",
175 | ]
176 | ```
177 |
178 | - **_hatch.toml_**
179 |
180 | ```toml
181 | [envs.]
182 | type = "pip-compile"
183 | pip-compile-args = [
184 | "--index-url",
185 | "https://pypi.org/simple",
186 | ]
187 | ```
188 |
189 | ## pip-compile-verbose
190 |
191 | Set to `true` to run `pip-compile` in verbose mode instead of quiet mode.
192 |
193 | Optionally, if you would like to silence any warnings set the `pip-compile-verbose` option
194 | to `false`.
195 |
196 | - **_pyproject.toml_**
197 |
198 | ```toml
199 | [tool.hatch.envs.]
200 | type = "pip-compile"
201 | pip-compile-verbose = true
202 | ```
203 |
204 | - **_hatch.toml_**
205 |
206 | ```toml
207 | [envs.]
208 | type = "pip-compile"
209 | pip-compile-verbose = true
210 | ```
211 |
212 | ## pip-compile-installer
213 |
214 | Whether to use [pip], [pip-sync], or [uv] to install dependencies into the project. Defaults
215 | to `pip`. When you choose the `pip` option the plugin will run `pip install -r {lockfile}`
216 | under the hood to install the dependencies. When you choose the `pip-sync` option
217 | `pip-sync {lockfile}` is invoked by the plugin. [uv] is a drop in replacement for
218 | `pip`, it has the same behavior as `pip` installer, `uv pip install -r {lockfile}`.
219 |
220 | The key difference between these options is that `pip-sync` will uninstall any packages that are
221 | not in the lockfile and remove them from your environment. `pip-sync` is useful if you want to
222 | ensure that your environment is exactly the same as the lockfile. If the environment should
223 | be used across different Python versions and platforms `pip` is the safer option to use.
224 |
225 | - **_pyproject.toml_**
226 |
227 | ```toml
228 | [tool.hatch.envs.]
229 | type = "pip-compile"
230 | pip-compile-installer = "pip-sync"
231 | ```
232 |
233 | - **_hatch.toml_**
234 |
235 | ```toml
236 | [envs.]
237 | type = "pip-compile"
238 | pip-compile-installer = "pip-sync"
239 | ```
240 |
241 | ## pip-compile-install-args
242 |
243 | Extra arguments to pass to `pip-compile-installer`. For example, if you'd like to use `pip` as the
244 | installer but want to pass the `--no-deps` flag to `pip install` you can do so with this option:
245 |
246 | - **_pyproject.toml_**
247 |
248 | ```toml
249 | [tool.hatch.envs.]
250 | type = "pip-compile"
251 | pip-compile-installer = "pip"
252 | pip-compile-install-args = [
253 | "--no-deps"
254 | ]
255 | ```
256 |
257 | - **_hatch.toml_**
258 |
259 | ```toml
260 | [envs.]
261 | type = "pip-compile"
262 | pip-compile-installer = "pip"
263 | pip-compile-install-args = [
264 | "--no-deps"
265 | ]
266 | ```
267 |
268 | ## Alternate Install Locations
269 |
270 | If you'd like to install dependencies into a different location, you must configure
271 | this at the `hatch` level in your `config.toml` file:
272 |
273 | ```toml
274 | [dirs.env]
275 | virtual = ".venv"
276 | pip-compile = ".venv"
277 | ```
278 |
279 | Alternatively, you can set this from the commandline:
280 |
281 | ```shell
282 | hatch config set dirs.env.pip-compile ".venv"
283 | ```
284 |
285 | [pip-sync]: https://github.com/jazzband/pip-tools
286 | [pip]: https://pip.pypa.io
287 | [inheritance]: hhttps://hatch.pypa.io/latest/config/environment/overview/#inheritance
288 | [uv]: https://github.com/astral-sh/uv
289 |
--------------------------------------------------------------------------------
/docs/gen_pages.py:
--------------------------------------------------------------------------------
1 | """
2 | Generate the code reference pages and navigation.
3 | """
4 |
5 | import logging
6 | from pathlib import Path
7 |
8 | import mkdocs_gen_files
9 |
10 | logger = logging.getLogger(__name__)
11 |
12 | project_dir = Path(__file__).resolve().parent.parent
13 | source_code = project_dir.joinpath("hatch_pip_compile")
14 |
15 | for path in sorted(source_code.rglob("*.py")):
16 | module_path = path.relative_to(project_dir).with_suffix("")
17 | doc_path = path.relative_to(source_code).with_suffix(".md")
18 | full_doc_path = Path("reference", doc_path)
19 |
20 | parts = tuple(module_path.parts)
21 | if parts[-1] == "__init__":
22 | parts = parts[:-1]
23 | doc_path = doc_path.with_name("index.md")
24 | full_doc_path = full_doc_path.with_name("index.md")
25 | elif parts[-1] == "__main__":
26 | continue
27 |
28 | with mkdocs_gen_files.open(full_doc_path, "w") as fd:
29 | fd.write(f"# `{parts[-1]}`\n\n::: {'.'.join(parts)}")
30 |
31 | mkdocs_gen_files.set_edit_path(full_doc_path, path)
32 |
33 | readme_content = Path("README.md").read_text(encoding="utf-8")
34 | readme_content = readme_content.replace("](docs/", "](")
35 | # Exclude parts that are between two exact `` lines
36 | readme_content = "\n".join(readme_content.split("\n\n")[::2])
37 | with mkdocs_gen_files.open("index.md", "w") as index_file:
38 | index_file.write(readme_content)
39 |
--------------------------------------------------------------------------------
/docs/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/juftin/hatch-pip-compile/9337724557a2a8efe663d76a98faf96d3176d063/docs/logo.png
--------------------------------------------------------------------------------
/docs/notes.md:
--------------------------------------------------------------------------------
1 | # Notes
2 |
3 | ## Dev Dependencies
4 |
5 | Using the default hatch configuration, dev dependencies listed in your
6 | `default` environment (like `pytest`) will be included on the default lockfile
7 | (`requirements.txt`). If you want to remove your dev dependencies
8 | from the lockfile you must remove them from the `default` environment
9 | on your `pyproject.toml` / `hatch.toml` file.
10 |
11 | ## Disabling Changes to the Lockfile
12 |
13 | In some scenarios, like in CI/CD, you may want to prevent the plugin from
14 | making changes to the lockfile. If you set the `PIP_COMPILE_DISABLE`
15 | environment variable to any non-empty value, the plugin will raise an error
16 | if it detects that the lockfile needs to be updated.
17 |
18 | ```shell
19 | PIP_COMPILE_DISABLE=1 hatch env run python --version
20 | ```
21 |
22 | ## Manual Installation
23 |
24 | If you want to manually install this plugin instead of adding it to the
25 | `[tool.hatch.env]` table, you can do so with [pipx]:
26 |
27 | ```bash
28 | pipx install hatch
29 | pipx inject hatch hatch-pip-compile
30 | ```
31 |
32 | `pipx` also supports upgrading the plugin when any new versions are released:
33 |
34 | ```shell
35 | pipx runpip hatch install --upgrade hatch-pip-compile
36 | ```
37 |
38 | Alternatively, you can install the plugin directly with [pip]:
39 |
40 | ```bash
41 | pip install hatch hatch-pip-compile
42 | ```
43 |
44 | [pipx]: https://github.com/pypa/pipx
45 | [pip]: https://pip.pypa.io
46 |
--------------------------------------------------------------------------------
/docs/upgrading.md:
--------------------------------------------------------------------------------
1 | # Upgrading Dependencies
2 |
3 | Upgrading all dependencies can be as simple as deleting your lockfile and
4 | recreating it by reactivating the environment:
5 |
6 | ```shell
7 | rm requirements.txt
8 | hatch env run --env default -- python --version
9 | ```
10 |
11 | If you're a user of the `--upgrade` / `--upgrade-package` options on `pip-compile`,
12 | these features can be enabled on this plugin by using the environment variables
13 | `PIP_COMPILE_UPGRADE` and `PIP_COMPILE_UPGRADE_PACKAGE`. When either of these
14 | environment variables are set `hatch` will force the lockfile to be regenerated
15 | whenever the environment is activated.
16 |
17 | > NOTE: **command line interface**
18 | >
19 | > `hatch-pip-compile` also makes a CLI available to handle the
20 | > the `PIP_COMPILE_UPGRADE` / `PIP_COMPILE_UPGRADE_PACKAGE` workflow
21 | > automatically. See the [hatch-pip-compile CLI](cli_usage.md#using-the-hatch-pip-compile-cli)
22 | > section for more information.
23 |
24 | To run with `upgrade` functionality on the `default` environment:
25 |
26 | ```shell
27 | PIP_COMPILE_UPGRADE=1 hatch env run --env default -- python --version
28 | ```
29 |
30 | To run with `upgrade-package` functionality on the `docs` environment:
31 |
32 | ```shell
33 | PIP_COMPILE_UPGRADE_PACKAGE="mkdocs,mkdocs-material" hatch env run --env docs -- python --version
34 | ```
35 |
36 | The above commands call `python --version` on a particular environment,
37 | but the same behavior applies to any script that activates the environment.
38 |
--------------------------------------------------------------------------------
/hatch_pip_compile/__about__.py:
--------------------------------------------------------------------------------
1 | """
2 | hatch-pip-compile info file
3 | """
4 |
5 | __author__ = "Justin Flannery"
6 | __email__ = "juftin@juftin.com"
7 | __application__ = "hatch-pip-compile"
8 | __version__ = "1.11.5"
9 |
--------------------------------------------------------------------------------
/hatch_pip_compile/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | hatch-pip-compile
3 | """
4 |
5 | from hatch_pip_compile.__about__ import __application__, __author__, __email__, __version__
6 |
7 | __all__ = [
8 | "__application__",
9 | "__version__",
10 | "__author__",
11 | "__email__",
12 | ]
13 |
--------------------------------------------------------------------------------
/hatch_pip_compile/__main__.py:
--------------------------------------------------------------------------------
1 | """
2 | hatch_pip_compile module hook
3 | """
4 |
5 | from hatch_pip_compile.cli import cli
6 |
7 | if __name__ == "__main__":
8 | cli()
9 |
--------------------------------------------------------------------------------
/hatch_pip_compile/base.py:
--------------------------------------------------------------------------------
1 | """
2 | Base classes for hatch-pip-compile
3 | """
4 |
5 | from __future__ import annotations
6 |
7 | from typing import TYPE_CHECKING, ClassVar
8 |
9 | from hatchling.dep.core import dependencies_in_sync
10 | from packaging.requirements import Requirement
11 |
12 | if TYPE_CHECKING:
13 | from hatch_pip_compile.plugin import PipCompileEnvironment
14 |
15 |
16 | class HatchPipCompileBase:
17 | """
18 | Base Class for hatch-pip-compile tools
19 | """
20 |
21 | pypi_dependencies: ClassVar[list[str]] = []
22 |
23 | def __init__(self, environment: PipCompileEnvironment) -> None:
24 | """
25 | Inject the environment into the base class
26 | """
27 | self.environment = environment
28 | self.pypi_dependencies_installed = False
29 |
30 | def install_pypi_dependencies(self) -> None:
31 | """
32 | Install the resolver from PyPI
33 | """
34 | if not self.pypi_dependencies:
35 | return
36 | elif self.pypi_dependencies_installed:
37 | return
38 | with self.environment.safe_activation():
39 | in_sync = dependencies_in_sync(
40 | requirements=[Requirement(item) for item in self.pypi_dependencies],
41 | sys_path=self.environment.virtual_env.sys_path,
42 | environment=self.environment.virtual_env.environment,
43 | )
44 | if not in_sync:
45 | self.environment.plugin_check_command(
46 | self.environment.construct_pip_install_command(self.pypi_dependencies)
47 | )
48 | self.pypi_dependencies_installed = True
49 |
--------------------------------------------------------------------------------
/hatch_pip_compile/cli.py:
--------------------------------------------------------------------------------
1 | """
2 | hatch-pip-compile CLI
3 | """
4 |
5 | from __future__ import annotations
6 |
7 | import dataclasses
8 | import json
9 | import os
10 | import subprocess
11 | from typing import Any, Sequence
12 |
13 | import click
14 | import rich.traceback
15 |
16 | from hatch_pip_compile.__about__ import __application__, __version__
17 |
18 |
19 | @dataclasses.dataclass
20 | class HatchCommandRunner:
21 | """
22 | Hatch Command Runner
23 | """
24 |
25 | environments: Sequence[str] = dataclasses.field(default_factory=list)
26 | upgrade: bool = False
27 | upgrade_all: bool = False
28 | upgrade_packages: Sequence[str] = dataclasses.field(default_factory=list)
29 |
30 | former_env_vars: dict[str, Any] = dataclasses.field(init=False, default_factory=dict)
31 | console: rich.console.Console = dataclasses.field(init=False)
32 | supported_environments: set[str] = dataclasses.field(init=False)
33 |
34 | def __post_init__(self):
35 | """
36 | Initialize the internal state
37 | """
38 | self.console = rich.console.Console()
39 | rich.traceback.install(show_locals=True, console=self.console)
40 | self.supported_environments = self._get_supported_environments()
41 | if all(
42 | [not self.environments, "default" in self.supported_environments, not self.upgrade_all]
43 | ):
44 | self.environments = ["default"]
45 | elif not self.environments and not self.upgrade_all:
46 | msg = "Either `--all` or an environment name must be specified"
47 | raise click.BadParameter(msg)
48 | elif self.upgrade_all:
49 | self.environments = list(self.supported_environments)
50 | unsupported_environments = set(self.environments).difference(self.supported_environments)
51 | if unsupported_environments:
52 | msg = (
53 | f"The following environments are not supported or unknown: "
54 | f"{', '.join(unsupported_environments)}. "
55 | f"Supported environments are: {', '.join(sorted(self.supported_environments))}"
56 | )
57 | raise click.BadParameter(msg)
58 |
59 | def __enter__(self) -> HatchCommandRunner:
60 | """
61 | Set the environment variables
62 | """
63 | env_vars = {"__PIP_COMPILE_FORCE__": "1"}
64 | if self.upgrade:
65 | env_vars["PIP_COMPILE_UPGRADE"] = "1"
66 | self.console.print(
67 | "[bold green]hatch-pip-compile[/bold green]: Upgrading all dependencies"
68 | )
69 | elif self.upgrade_packages:
70 | env_vars["PIP_COMPILE_UPGRADE_PACKAGE"] = ",".join(self.upgrade_packages)
71 | message = (
72 | "[bold green]hatch-pip-compile[/bold green]: "
73 | f"Upgrading packages: {', '.join(self.upgrade_packages)}"
74 | )
75 | self.console.print(message)
76 | self.former_env_vars = {
77 | key: os.environ.get(key) for key in env_vars.keys() if os.environ.get(key) is not None
78 | }
79 | os.environ.update(env_vars)
80 | return self
81 |
82 | def __exit__(self, *args, **kwargs):
83 | """
84 | Restore the environment variables
85 | """
86 | os.environ.update(self.former_env_vars)
87 |
88 | def hatch_cli(self):
89 | """
90 | Run the `hatch` CLI
91 | """
92 | self.console.print(
93 | "[bold green]hatch-pip-compile[/bold green]: Targeting environments: "
94 | f"{', '.join(sorted(self.environments))}"
95 | )
96 | for environment in sorted(self.environments):
97 | environment_command = [
98 | "hatch",
99 | "env",
100 | "run",
101 | "--env",
102 | environment,
103 | "--",
104 | "python",
105 | "--version",
106 | ]
107 | self.console.print(
108 | f"[bold green]hatch-pip-compile[/bold green]: Running "
109 | f"`[bold blue]{' '.join(environment_command)}`[/bold blue]"
110 | )
111 | result = subprocess.run(
112 | args=environment_command,
113 | capture_output=True,
114 | check=False,
115 | )
116 | if result.returncode != 0: # pragma: no cover
117 | self.console.print(
118 | "[bold yellow]hatch command[/bold yellow]: "
119 | f"[bold blue]`{' '.join(environment_command)}`[/bold blue]"
120 | )
121 | self.console.print(result.stdout.decode("utf-8"))
122 | self.console.print(
123 | "[bold red]hatch-pip-compile[/bold red]: Error running hatch command"
124 | )
125 | raise click.exceptions.Exit(1)
126 |
127 | @classmethod
128 | def _get_supported_environments(cls) -> set[str]:
129 | """
130 | Get the names of the environments from `hatch env show --json`
131 |
132 | Returns
133 | -------
134 | List[str]
135 | The name of the environments
136 | """
137 | result = subprocess.run(
138 | args=["hatch", "env", "show", "--json"],
139 | capture_output=True,
140 | check=True,
141 | )
142 | environment_dict: dict[str, Any] = json.loads(result.stdout)
143 | return {
144 | key for key, value in environment_dict.items() if value.get("type") == "pip-compile"
145 | }
146 |
147 |
148 | @click.command("hatch-pip-compile")
149 | @click.version_option(version=__version__, prog_name=__application__)
150 | @click.argument("environment", default=None, type=click.STRING, required=False, nargs=-1)
151 | @click.option(
152 | "-U",
153 | "--upgrade/--no-upgrade",
154 | is_flag=True,
155 | default=False,
156 | help="Try to upgrade all dependencies to their latest versions",
157 | )
158 | @click.option(
159 | "-P",
160 | "--upgrade-package",
161 | "upgrade_packages",
162 | nargs=1,
163 | multiple=True,
164 | help="Specify a particular package to upgrade; may be used more than once",
165 | )
166 | @click.option(
167 | "--all",
168 | "upgrade_all",
169 | is_flag=True,
170 | default=False,
171 | help="Upgrade all environments",
172 | )
173 | def cli(
174 | environment: Sequence[str],
175 | upgrade: bool,
176 | upgrade_packages: Sequence[str],
177 | upgrade_all: bool,
178 | ):
179 | """
180 | Upgrade your `hatch-pip-compile` managed dependencies
181 | from the command line.
182 | """
183 | with HatchCommandRunner(
184 | environments=environment,
185 | upgrade=upgrade,
186 | upgrade_packages=upgrade_packages,
187 | upgrade_all=upgrade_all,
188 | ) as hatch_runner:
189 | hatch_runner.hatch_cli()
190 |
191 |
192 | if __name__ == "__main__":
193 | cli()
194 |
--------------------------------------------------------------------------------
/hatch_pip_compile/exceptions.py:
--------------------------------------------------------------------------------
1 | """
2 | hatch-pip-compile exceptions
3 | """
4 |
5 |
6 | class HatchPipCompileError(Exception):
7 | """
8 | Base exception for hatch-pip-compile
9 | """
10 |
11 |
12 | class LockFileNotFoundError(HatchPipCompileError, FileNotFoundError):
13 | """
14 | A lock file was not found
15 | """
16 |
17 |
18 | class LockFileError(HatchPipCompileError, ValueError):
19 | """
20 | A lock file content Error
21 | """
22 |
--------------------------------------------------------------------------------
/hatch_pip_compile/hooks.py:
--------------------------------------------------------------------------------
1 | """
2 | Hatch Plugin Registration
3 | """
4 |
5 | from typing import Type
6 |
7 | from hatchling.plugin import hookimpl
8 |
9 | from hatch_pip_compile.plugin import PipCompileEnvironment
10 |
11 |
12 | @hookimpl
13 | def hatch_register_environment() -> Type[PipCompileEnvironment]:
14 | """
15 | Register the PipCompileEnvironment plugin with Hatch
16 | """
17 | return PipCompileEnvironment
18 |
--------------------------------------------------------------------------------
/hatch_pip_compile/installer.py:
--------------------------------------------------------------------------------
1 | """
2 | Package + Dependency Installers
3 | """
4 |
5 | from __future__ import annotations
6 |
7 | from abc import ABC, abstractmethod
8 | from typing import ClassVar
9 |
10 | from hatch.env.utils import add_verbosity_flag
11 |
12 | from hatch_pip_compile.base import HatchPipCompileBase
13 |
14 |
15 | class PluginInstaller(HatchPipCompileBase, ABC):
16 | """
17 | Package Installer for the plugin
18 |
19 | This abstract base class is used to define the interface for
20 | how the plugin should install packages and dependencies.
21 | """
22 |
23 | @abstractmethod
24 | def install_dependencies(self) -> None:
25 | """
26 | Install the dependencies
27 | """
28 |
29 | def sync_dependencies(self) -> None:
30 | """
31 | Sync the dependencies - same as `install_dependencies`
32 | """
33 | self.install_pypi_dependencies()
34 | self.install_dependencies()
35 |
36 | def construct_pip_install_command(self, args: list[str]) -> list[str]:
37 | """
38 | Construct a `pip install` command with the given arguments
39 | """
40 | return self.environment.construct_pip_install_command(args)
41 |
42 | def install_project(self) -> None:
43 | """
44 | Install the project (`--no-deps`)
45 | """
46 | self.install_pypi_dependencies()
47 | with self.environment.safe_activation():
48 | self.environment.plugin_check_command(
49 | self.construct_pip_install_command(args=["--no-deps", str(self.environment.root)])
50 | )
51 |
52 | def install_project_dev_mode(self) -> None:
53 | """
54 | Install the project in editable mode (`--no-deps`)
55 | """
56 | self.install_pypi_dependencies()
57 | with self.environment.safe_activation():
58 | self.environment.plugin_check_command(
59 | self.construct_pip_install_command(
60 | args=["--no-deps", "--editable", str(self.environment.root)]
61 | )
62 | )
63 |
64 |
65 | class PipInstaller(PluginInstaller):
66 | """
67 | Plugin Installer for `pip`
68 | """
69 |
70 | def install_dependencies(self) -> None:
71 | """
72 | Install the dependencies with `pip`
73 | """
74 | self.install_pypi_dependencies()
75 | with self.environment.safe_activation():
76 | if not self.environment.piptools_lock_file.exists():
77 | return
78 | extra_args = self.environment.config.get("pip-compile-install-args", [])
79 | args = [*extra_args, "--requirement", str(self.environment.piptools_lock_file)]
80 | install_command = self.construct_pip_install_command(args=args)
81 | self.environment.plugin_check_command(install_command)
82 |
83 |
84 | class UvInstaller(PipInstaller):
85 | """
86 | Plugin Installer for `uv`
87 | """
88 |
89 | pypi_dependencies: ClassVar[list[str]] = ["uv"]
90 |
91 | def construct_pip_install_command(self, args: list[str]) -> list[str]:
92 | """
93 | Construct a `pip install` command with the given arguments
94 | """
95 | command = [
96 | "python",
97 | "-m",
98 | "uv",
99 | "pip",
100 | "install",
101 | ]
102 | add_verbosity_flag(command, self.environment.verbosity, adjustment=-1)
103 | command.extend(args)
104 | return command
105 |
106 |
107 | class PipSyncInstaller(PluginInstaller):
108 | """
109 | Plugin Installer for `pip-sync`
110 | """
111 |
112 | pypi_dependencies: ClassVar[list[str]] = ["pip-tools"]
113 |
114 | def install_dependencies(self) -> None:
115 | """
116 | Install the dependencies with `pip-sync`
117 |
118 | In the event that there are no dependencies, pip-sync will
119 | uninstall everything in the environment before deleting the
120 | lockfile.
121 | """
122 | self.install_pypi_dependencies()
123 | cmd = [
124 | self.environment.virtual_env.python_info.executable,
125 | "-m",
126 | "piptools",
127 | "sync",
128 | "--verbose"
129 | if self.environment.config.get("pip-compile-verbose", None) is True
130 | else "--quiet",
131 | "--python-executable",
132 | str(self.environment.virtual_env.python_info.executable),
133 | ]
134 | if not self.environment.dependencies:
135 | self.environment.piptools_lock_file.write_text("")
136 | extra_args = self.environment.config.get("pip-compile-install-args", [])
137 | cmd.extend(extra_args)
138 | cmd.append(str(self.environment.piptools_lock_file))
139 | self.environment.plugin_check_command(cmd)
140 | if not self.environment.dependencies:
141 | self.environment.piptools_lock_file.unlink()
142 |
143 | def _full_install(self) -> None:
144 | """
145 | Run the full install process
146 |
147 | 1) Run pip-compile (if necessary)
148 | 2) Run pip-sync
149 | 3) (re)install project
150 | """
151 | with self.environment.safe_activation():
152 | self.environment.run_pip_compile()
153 | self.install_dependencies()
154 | if not self.environment.skip_install:
155 | if self.environment.dev_mode:
156 | super().install_project_dev_mode()
157 | else:
158 | super().install_project()
159 |
160 | def sync_dependencies(self):
161 | """
162 | Sync dependencies
163 | """
164 | self._full_install()
165 |
166 | def install_project(self):
167 | """
168 | Install the project the first time
169 |
170 | The same implementation as `_full_install`
171 | due to the way `pip-sync` uninstalls our root package
172 | """
173 | self._full_install()
174 |
175 | def install_project_dev_mode(self):
176 | """
177 | Install the project the first time in dev mode
178 |
179 | The same implementation as `_full_install`
180 | due to the way `pip-sync` uninstalls our root package
181 | """
182 | self._full_install()
183 |
--------------------------------------------------------------------------------
/hatch_pip_compile/lock.py:
--------------------------------------------------------------------------------
1 | """
2 | hatch-pip-compile header operations
3 | """
4 |
5 | from __future__ import annotations
6 |
7 | import hashlib
8 | import logging
9 | import pathlib
10 | import re
11 | from textwrap import dedent
12 | from typing import Iterable
13 |
14 | from packaging.requirements import Requirement
15 | from packaging.version import Version
16 | from piptools._compat.pip_compat import PipSession, parse_requirements
17 |
18 | from hatch_pip_compile.base import HatchPipCompileBase
19 |
20 | logger = logging.getLogger(__name__)
21 |
22 |
23 | class PipCompileLock(HatchPipCompileBase):
24 | """
25 | Pip Compile Lock File Operations
26 | """
27 |
28 | def process_lock(self, lockfile: pathlib.Path) -> None:
29 | """
30 | Post process lockfile
31 | """
32 | version = f"{self.current_python_version.major}.{self.current_python_version.minor}"
33 | raw_prefix = f"""
34 | #
35 | # This file is autogenerated by hatch-pip-compile with Python {version}
36 | #
37 | """
38 | prefix = dedent(raw_prefix).strip()
39 | joined_dependencies = "\n".join([f"# - {dep}" for dep in self.environment.dependencies])
40 | lockfile_text = lockfile.read_text()
41 | cleaned_input_file = self.replace_temporary_lockfile(lockfile_text=lockfile_text)
42 | if self.environment.piptools_constraints_file is not None:
43 | lockfile_contents = self.environment.piptools_constraints_file.read_bytes()
44 | cross_platform_contents = lockfile_contents.replace(b"\r\n", b"\n")
45 | constraint_sha = hashlib.sha256(cross_platform_contents).hexdigest()
46 | constraints_path = self.environment.piptools_constraints_file.relative_to(
47 | self.environment.root
48 | ).as_posix()
49 | constraints_line = f"# [constraints] {constraints_path} (SHA256: {constraint_sha})"
50 | joined_dependencies = "\n".join([constraints_line, "#", joined_dependencies])
51 | cleaned_input_file = re.sub(
52 | r"-c \S*",
53 | lambda _: f"-c {constraints_path}",
54 | cleaned_input_file,
55 | )
56 | prefix += "\n" + joined_dependencies + "\n#"
57 | new_text = prefix + "\n\n" + cleaned_input_file
58 | lockfile.write_text(new_text)
59 |
60 | def read_header_requirements(self) -> list[Requirement]:
61 | """
62 | Read requirements from lock file header
63 | """
64 | lock_file_text = self.environment.piptools_lock_file.read_text()
65 | parsed_requirements = []
66 | for line in lock_file_text.splitlines():
67 | if line.startswith("# - "):
68 | requirement = Requirement(line[4:])
69 | parsed_requirements.append(requirement)
70 | elif not line.startswith("#"):
71 | break
72 | return parsed_requirements
73 |
74 | @property
75 | def current_python_version(self) -> Version:
76 | """
77 | Get python version
78 |
79 | In the case of running as a hatch plugin, the `virtualenv` will be set,
80 | otherwise it will be None and the Python version will be read differently.
81 | """
82 | if self.environment.virtual_env is not None:
83 | return Version(self.environment.virtual_env.environment["python_version"])
84 | else:
85 | msg = "VirtualEnv is not set"
86 | raise NotImplementedError(msg)
87 |
88 | @property
89 | def lock_file_version(self) -> Version | None:
90 | """
91 | Get lock file version
92 | """
93 | lock_file_text = self.environment.piptools_lock_file.read_text()
94 | match = re.search(
95 | r"# This file is autogenerated by hatch-pip-compile with Python (.*)", lock_file_text
96 | )
97 | if match is None:
98 | logger.error(
99 | "[hatch-pip-compile] Non hatch-pip-compile lock file detected (%s)",
100 | self.environment.piptools_lock_file.name,
101 | )
102 | return None
103 | return Version(match.group(1))
104 |
105 | def compare_python_versions(self, verbose: bool | None = None) -> bool:
106 | """
107 | Compare python versions
108 |
109 | Parameters
110 | ----------
111 | verbose : Optional[bool]
112 | Print warning if python versions are different, by default None
113 | which will print the warning. Used as a plugin flag.
114 | """
115 | lock_version = self.lock_file_version
116 | if lock_version is None:
117 | return False
118 | current_version = self.current_python_version
119 | match = (current_version.major == lock_version.major) and (
120 | current_version.minor == lock_version.minor
121 | )
122 | if match is False and verbose is not False:
123 | logger.error(
124 | "[hatch-pip-compile] Your Python version is different "
125 | "from the lock file, your results may vary."
126 | )
127 | return lock_version == current_version
128 |
129 | def compare_requirements(self, requirements: Iterable[Requirement]) -> bool:
130 | """
131 | Compare requirements
132 |
133 | Parameters
134 | ----------
135 | requirements : Iterable[Requirement]
136 | List of requirements to compare against the lock file
137 | """
138 | lock_requirements = self.read_header_requirements()
139 | return set(requirements) == set(lock_requirements)
140 |
141 | def compare_constraint_sha(self, sha: str) -> bool:
142 | """
143 | Compare SHA to the SHA on the lockfile
144 | """
145 | lock_file_text = self.environment.piptools_lock_file.read_text()
146 | match = re.search(r"# \[constraints\] \S* \(SHA256: (.*)\)", lock_file_text)
147 | if match is None:
148 | return False
149 | return match.group(1).strip() == sha.strip()
150 |
151 | def get_file_content_hash(self) -> str:
152 | """
153 | Get hash of lock file
154 | """
155 | lockfile_contents = self.environment.piptools_lock_file.read_bytes()
156 | cross_platform_contents = lockfile_contents.replace(b"\r\n", b"\n")
157 | return hashlib.sha256(cross_platform_contents).hexdigest()
158 |
159 | def read_lock_requirements(self) -> list[Requirement]:
160 | """
161 | Read all requirements from lock file
162 | """
163 | if not self.environment.dependencies:
164 | return []
165 | install_requirements = parse_requirements(
166 | str(self.environment.piptools_lock_file),
167 | session=PipSession(),
168 | )
169 | return [ireq.req for ireq in install_requirements] # type: ignore[misc]
170 |
171 | def replace_temporary_lockfile(self, lockfile_text: str) -> str:
172 | """
173 | Replace the temporary lockfile with the new lockfile
174 | """
175 | cleaned_input_file = re.sub(
176 | rf"-r \S*[\\/]{self.environment.name}\.in",
177 | f"hatch.envs.{self.environment.name}",
178 | lockfile_text,
179 | )
180 | return cleaned_input_file
181 |
--------------------------------------------------------------------------------
/hatch_pip_compile/plugin.py:
--------------------------------------------------------------------------------
1 | """
2 | hatch-pip-compile plugin
3 | """
4 |
5 | import functools
6 | import hashlib
7 | import logging
8 | import os
9 | import pathlib
10 | import shutil
11 | import tempfile
12 | from subprocess import CompletedProcess
13 | from typing import Any, ClassVar, Dict, List, Optional, Type, Union
14 |
15 | import hatch.cli
16 | from hatch.env.virtual import VirtualEnvironment
17 | from hatch.utils.platform import Platform
18 | from hatchling.dep.core import dependencies_in_sync
19 |
20 | from hatch_pip_compile.exceptions import HatchPipCompileError
21 | from hatch_pip_compile.installer import PipInstaller, PipSyncInstaller, PluginInstaller, UvInstaller
22 | from hatch_pip_compile.lock import PipCompileLock
23 | from hatch_pip_compile.resolver import BaseResolver, PipCompileResolver, UvResolver
24 |
25 | logger = logging.getLogger(__name__)
26 |
27 |
28 | class PipCompileEnvironment(VirtualEnvironment):
29 | """
30 | Virtual Environment supported by pip-compile
31 | """
32 |
33 | PLUGIN_NAME: ClassVar[str] = "pip-compile"
34 | default_env_name: ClassVar[str] = "default"
35 | dependency_resolvers: ClassVar[Dict[str, Type[BaseResolver]]] = {
36 | "pip-compile": PipCompileResolver,
37 | "uv": UvResolver,
38 | }
39 | dependency_installers: ClassVar[Dict[str, Type[PluginInstaller]]] = {
40 | "pip": PipInstaller,
41 | "pip-sync": PipSyncInstaller,
42 | "uv": UvInstaller,
43 | }
44 |
45 | def __repr__(self):
46 | """
47 | Get representation of PipCompileEnvironment
48 | """
49 | return f"<{self.__class__.__name__} - {self.name}>"
50 |
51 | def __init__(self, *args, **kwargs) -> None:
52 | """
53 | Initialize PipCompileEnvironment with extra attributes
54 | """
55 | super().__init__(*args, **kwargs)
56 | lock_filename_config = self.config.get("lock-filename")
57 | if lock_filename_config is None:
58 | if self.name == self.default_env_name:
59 | lock_filename = "requirements.txt"
60 | else:
61 | lock_filename = f"requirements/requirements-{self.name}.txt"
62 | else:
63 | with self.metadata.context.apply_context(self.context):
64 | lock_filename = self.metadata.context.format(lock_filename_config)
65 | self.piptools_lock_file = self.root / lock_filename
66 | self.piptools_lock = PipCompileLock(environment=self)
67 | install_method = self.config.get("pip-compile-installer", "pip")
68 | resolve_method = self.config.get("pip-compile-resolver", "pip-compile")
69 | if install_method not in self.dependency_installers.keys():
70 | msg = (
71 | f"Invalid pip-compile-installer: {install_method} - "
72 | f"must be one of {', '.join(self.dependency_installers.keys())}"
73 | )
74 | raise HatchPipCompileError(msg)
75 | if resolve_method not in self.dependency_resolvers.keys():
76 | msg = (
77 | f"Invalid pip-compile-resolver: {resolve_method} - "
78 | f"must be one of {', '.join(self.dependency_resolvers.keys())}"
79 | )
80 | raise HatchPipCompileError(msg)
81 | resolver_class = self.dependency_resolvers[resolve_method]
82 | installer_class = self.dependency_installers[install_method]
83 | self.resolver: BaseResolver = resolver_class(environment=self)
84 | self.installer: PluginInstaller = installer_class(environment=self)
85 |
86 | @staticmethod
87 | def get_option_types() -> Dict[str, Any]:
88 | """
89 | Get option types
90 | """
91 | return { # pragma: no cover
92 | "lock-filename": str,
93 | "pip-compile-hashes": bool,
94 | "pip-compile-args": list,
95 | "pip-compile-constraint": str,
96 | "pip-compile-installer": str,
97 | "pip-compile-install-args": list,
98 | "pip-compile-resolver": str,
99 | }
100 |
101 | def dependency_hash(self) -> str:
102 | """
103 | Get the dependency hash
104 | """
105 | self.run_pip_compile()
106 | hatch_hash = super().dependency_hash()
107 | if not self.dependencies:
108 | return hatch_hash
109 | else:
110 | lockfile_hash = self.piptools_lock.get_file_content_hash()
111 | return hashlib.sha256(f"{hatch_hash}-{lockfile_hash}".encode()).hexdigest()
112 |
113 | def run_pip_compile(self) -> None:
114 | """
115 | Run pip-compile if necessary
116 | """
117 | self.prepare_environment()
118 | if not self.lockfile_up_to_date:
119 | with self.safe_activation():
120 | self.resolver.install_pypi_dependencies()
121 | if self.piptools_lock_file.exists():
122 | _ = self.piptools_lock.compare_python_versions(
123 | verbose=self.config.get("pip-compile-verbose", None)
124 | )
125 | self.pip_compile_cli()
126 |
127 | def pip_compile_cli(self) -> None:
128 | """
129 | Run pip-compile
130 | """
131 | if not self.dependencies:
132 | self.piptools_lock_file.unlink(missing_ok=True)
133 | self.lockfile_up_to_date = True
134 | return
135 | no_compile = bool(os.getenv("PIP_COMPILE_DISABLE"))
136 | if no_compile:
137 | msg = "hatch-pip-compile is disabled but attempted to run a lockfile update."
138 | raise HatchPipCompileError(msg)
139 | with tempfile.TemporaryDirectory() as tmpdir:
140 | tmp_path = pathlib.Path(tmpdir)
141 | input_file = tmp_path / f"{self.name}.in"
142 | output_file = tmp_path / "lock.txt"
143 | input_file.write_text("\n".join([*self.dependencies, ""]))
144 | if self.piptools_lock_file.exists():
145 | shutil.copy(self.piptools_lock_file, output_file)
146 | self.piptools_lock_file.parent.mkdir(exist_ok=True, parents=True)
147 | cmd = self.resolver.get_pip_compile_args(
148 | input_file=input_file,
149 | output_file=output_file,
150 | )
151 | self.plugin_check_command(cmd)
152 | self.piptools_lock.process_lock(lockfile=output_file)
153 | shutil.move(output_file, self.piptools_lock_file)
154 | self.lockfile_up_to_date = True
155 |
156 | def install_project(self) -> None:
157 | """
158 | Install the project (`--no-deps`)
159 | """
160 | self.installer.install_project()
161 |
162 | def install_project_dev_mode(self) -> None:
163 | """
164 | Install the project in editable mode (`--no-deps`)
165 | """
166 | self.installer.install_project_dev_mode()
167 |
168 | @functools.cached_property
169 | def lockfile_up_to_date(self) -> bool:
170 | """
171 | Check if the lockfile is up-to-date
172 |
173 | Behavior
174 | --------
175 | 1) If there are no dependencies and no lock file, exit early and return True.
176 | 2) If the constraint file / environment is out of date, sync it and return False.
177 | 3) If there are no dependencies and a lock file, return False.
178 | 4) If there are dependencies and no lock file, return False.
179 | 5) If a force upgrade is requested, return False.
180 | 6) If there are dependencies and a lock file...
181 | a) If there is a constraint file...
182 | i) If the file is valid but the SHA is different, return False.
183 | b) If the lock file dependencies aren't current, return False.
184 | c) If the lock file dependencies are current but the lockfile
185 | has a different sha than its constraints file, return False.
186 | 7) Otherwise, return True.
187 | """
188 | upgrade = os.getenv("PIP_COMPILE_UPGRADE") or False
189 | upgrade_packages = os.getenv("PIP_COMPILE_UPGRADE_PACKAGE") or False
190 | pip_compile_force = bool(os.getenv("__PIP_COMPILE_FORCE__"))
191 | force_upgrade = any(
192 | [
193 | upgrade is not False,
194 | upgrade_packages is not False,
195 | pip_compile_force is not False,
196 | ]
197 | )
198 | if not self.dependencies and not self.piptools_lock_file.exists():
199 | return True
200 | if self.piptools_constraints_file:
201 | valid_constraint = self.validate_constraints_file(
202 | constraints_file=self.piptools_constraints_file, environment=self.constraint_env
203 | )
204 | if not valid_constraint:
205 | return False
206 | if not self.dependencies and self.piptools_lock_file.exists():
207 | return False
208 | elif force_upgrade:
209 | return False
210 | elif self.dependencies and not self.piptools_lock_file.exists():
211 | return False
212 | elif self.dependencies and self.piptools_lock_file.exists():
213 | if self.piptools_constraints_file:
214 | current_sha = self.constraint_env.piptools_lock.get_file_content_hash()
215 | sha_match = self.piptools_lock.compare_constraint_sha(sha=current_sha)
216 | if sha_match is False:
217 | return False
218 | expected_dependencies = self.piptools_lock.compare_requirements(
219 | requirements=self.dependencies_complex
220 | )
221 | if not expected_dependencies:
222 | return False
223 | return True
224 |
225 | def dependencies_in_sync(self):
226 | """
227 | Whether the dependencies are in sync
228 | """
229 | if not self.lockfile_up_to_date:
230 | return False
231 | else:
232 | with self.safe_activation():
233 | return dependencies_in_sync(
234 | self.piptools_lock.read_lock_requirements(),
235 | sys_path=self.virtual_env.sys_path,
236 | environment=self.virtual_env.environment,
237 | )
238 |
239 | def sync_dependencies(self) -> None:
240 | """
241 | Sync dependencies
242 | """
243 | self.run_pip_compile()
244 | self.installer.sync_dependencies()
245 |
246 | @property
247 | def piptools_constraints_file(self) -> Optional[pathlib.Path]:
248 | """
249 | Get the constraint file path
250 | """
251 | if self.constraint_env.name == self.name:
252 | return None
253 | else:
254 | return self.constraint_env.piptools_lock_file
255 |
256 | def get_piptools_environment(self, environment_name: str) -> "PipCompileEnvironment":
257 | """
258 | Get a `PipCompileEnvironment` instance for an environment
259 | other than the current instance. This is useful
260 | for recursively checking other environments for lock file
261 | validity and defining inheritance.
262 | """
263 | if environment_name not in self.pipools_environment_dict.keys():
264 | error_message = (
265 | f"[hatch-pip-compile] The environment {environment_name} does not exist."
266 | )
267 | raise HatchPipCompileError(error_message)
268 | if isinstance(self.app, hatch.cli.Application):
269 | env = self.app.get_environment(env_name=environment_name)
270 | else:
271 | env = PipCompileEnvironment(
272 | root=self.root,
273 | metadata=self.metadata,
274 | name=environment_name,
275 | config=self.pipools_environment_dict.get(environment_name, {}),
276 | matrix_variables=self.matrix_variables,
277 | data_directory=self.data_directory,
278 | isolated_data_directory=self.isolated_data_directory,
279 | platform=Platform(),
280 | verbosity=self.verbosity,
281 | app=self.app,
282 | )
283 | return env
284 |
285 | @functools.cached_property
286 | def constraint_env(self) -> "PipCompileEnvironment":
287 | """
288 | Get the constraint environment
289 | """
290 | constraint_env = self.config.get("pip-compile-constraint")
291 | if not constraint_env:
292 | return self
293 | elif self.name == constraint_env:
294 | return self
295 | environment = self.get_piptools_environment(environment_name=constraint_env)
296 | if environment.config.get("type") != self.PLUGIN_NAME:
297 | logger.error("The constraint environment is not a hatch-pip-compile environment.")
298 | return self
299 | elif not environment.dependencies:
300 | return self
301 | else:
302 | return environment
303 |
304 | def validate_constraints_file(
305 | self, constraints_file: pathlib.Path, environment: "PipCompileEnvironment"
306 | ) -> bool:
307 | """
308 | Validate the constraints file
309 |
310 | Parameters
311 | ----------
312 | constraints_file : pathlib.Path
313 | The lock file
314 | environment : PipCompileEnvironment
315 | The environment to validate against
316 |
317 | Returns
318 | -------
319 | bool
320 | Whether the constraints file is valid
321 | """
322 | if not constraints_file.exists():
323 | self.constraint_env.run_pip_compile()
324 | return False
325 | else:
326 | up_to_date = environment.piptools_lock.compare_requirements(
327 | requirements=environment.dependencies_complex
328 | )
329 | if not up_to_date:
330 | self.constraint_env.run_pip_compile()
331 | return False
332 | return True
333 |
334 | @property
335 | def pipools_environment_dict(self) -> Dict[str, Any]:
336 | """
337 | Get the environment dictionary
338 | """
339 | return self.metadata.hatch.config.get("envs", {})
340 |
341 | def plugin_check_command(
342 | self, command: Union[str, List[str]], *, shell: bool = False, **kwargs: Any
343 | ) -> CompletedProcess:
344 | """
345 | Run a command from the virtualenv
346 | """
347 | with self.safe_activation():
348 | return self.virtual_env.platform.check_command(
349 | command=command,
350 | shell=shell,
351 | **kwargs,
352 | )
353 |
354 | def virtualenv_exists(self) -> bool:
355 | """
356 | Check if the virtualenv exists
357 | """
358 | try:
359 | _ = self.virtual_env.executables_directory
360 | return True
361 | except OSError:
362 | return False
363 |
364 | def prepare_environment(self) -> None:
365 | """
366 | Prepare the environment
367 |
368 | Ideally, we could access the `self.app` attribute,
369 | but this ultimately leads to a recursion error when
370 | `self.app.prepare_environment()` is called.
371 | """
372 | if not self.virtualenv_exists():
373 | self.create()
374 | if not self.dependencies_in_sync():
375 | self.sync_dependencies()
376 | if not self.skip_install:
377 | if self.dev_mode:
378 | self.install_project_dev_mode()
379 | else:
380 | self.install_project()
381 |
--------------------------------------------------------------------------------
/hatch_pip_compile/py.typed:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/juftin/hatch-pip-compile/9337724557a2a8efe663d76a98faf96d3176d063/hatch_pip_compile/py.typed
--------------------------------------------------------------------------------
/hatch_pip_compile/resolver.py:
--------------------------------------------------------------------------------
1 | """
2 | Dependency Resolvers
3 | """
4 |
5 | from __future__ import annotations
6 |
7 | import os
8 | from abc import ABC, abstractmethod
9 | from typing import ClassVar
10 |
11 | from hatch_pip_compile.base import HatchPipCompileBase
12 |
13 |
14 | class BaseResolver(HatchPipCompileBase, ABC):
15 | """
16 | Base Resolver for the plugin
17 | """
18 |
19 | resolver_options: ClassVar[list[str]] = []
20 |
21 | @property
22 | @abstractmethod
23 | def resolver_executable(self) -> list[str]:
24 | """
25 | Resolver Executable
26 | """
27 |
28 | def get_pip_compile_args(self, input_file: os.PathLike, output_file: os.PathLike) -> list[str]:
29 | """
30 | Get the pip compile arguments
31 | """
32 | upgrade = bool(os.getenv("PIP_COMPILE_UPGRADE"))
33 | upgrade_packages = os.getenv("PIP_COMPILE_UPGRADE_PACKAGE") or None
34 | upgrade_args = []
35 | upgrade_package_args = []
36 | if upgrade:
37 | upgrade_args.append("--upgrade")
38 | if upgrade_packages:
39 | upgrade_packages_sep = upgrade_packages.split(",")
40 | for package in upgrade_packages_sep:
41 | upgrade_package_args.append(f"--upgrade-package={package.strip()}")
42 | cmd = [
43 | *self.resolver_executable,
44 | "--verbose"
45 | if self.environment.config.get("pip-compile-verbose", None) is True
46 | else "--quiet",
47 | "--no-header",
48 | *self.resolver_options,
49 | ]
50 | if self.environment.config.get("pip-compile-hashes", False) is True:
51 | cmd.append("--generate-hashes")
52 | if self.environment.piptools_constraints_file is not None:
53 | cmd.extend(["--constraint", str(self.environment.piptools_constraints_file)])
54 | cmd.extend(self.environment.config.get("pip-compile-args", []))
55 | cmd.extend(upgrade_args)
56 | cmd.extend(upgrade_package_args)
57 | cmd.extend(["--output-file", str(output_file), str(input_file)])
58 | return cmd
59 |
60 |
61 | class PipCompileResolver(BaseResolver):
62 | """
63 | Pip Compile Resolver
64 | """
65 |
66 | pypi_dependencies: ClassVar[list[str]] = ["pip-tools"]
67 | resolver_options: ClassVar[list[str]] = ["--resolver=backtracking", "--strip-extras"]
68 |
69 | @property
70 | def resolver_executable(self) -> list[str]:
71 | """
72 | Resolver Executable
73 | """
74 | return [
75 | self.environment.virtual_env.python_info.executable,
76 | "-m",
77 | "piptools",
78 | "compile",
79 | ]
80 |
81 |
82 | class UvResolver(BaseResolver):
83 | """
84 | Uv Resolver
85 | """
86 |
87 | pypi_dependencies: ClassVar[list[str]] = ["uv"]
88 |
89 | @property
90 | def resolver_executable(self) -> list[str]:
91 | """
92 | Resolver Executable
93 | """
94 | return [
95 | self.environment.virtual_env.python_info.executable,
96 | "-m",
97 | "uv",
98 | "pip",
99 | "compile",
100 | ]
101 |
--------------------------------------------------------------------------------
/mkdocs.yaml:
--------------------------------------------------------------------------------
1 | # $schema: https://squidfunk.github.io/mkdocs-material/schema.json
2 |
3 | site_name: hatch-pip-compile
4 | nav:
5 | - Home 🏠: index.md
6 | - Examples 📚: examples.md
7 | - Upgrading 🚀: upgrading.md
8 | - Command Line Usage 📦: cli_usage.md
9 | - Notes 📝: notes.md
10 | - Command Line Docs ⌨️: cli.md
11 | - API Documentation 🤖: reference/
12 | - Contributing 🤝: contributing.md
13 | theme:
14 | favicon: https://juftin.com/favicon.ico
15 | logo: https://raw.githubusercontent.com/juftin/juftin/main/static/juftin.png
16 | name: material
17 | features:
18 | - navigation.tracking
19 | - content.code.annotate
20 | - content.code.copy
21 | palette:
22 | - media: "(prefers-color-scheme: light)"
23 | scheme: default
24 | accent: purple
25 | toggle:
26 | icon: material/weather-sunny
27 | name: Switch to dark mode
28 | - media: "(prefers-color-scheme: dark)"
29 | scheme: slate
30 | primary: black
31 | toggle:
32 | icon: material/weather-night
33 | name: Switch to light mode
34 | repo_url: https://github.com/juftin/hatch-pip-compile
35 | repo_name: hatch-pip-compile
36 | edit_uri: blob/main/docs/
37 | site_author: juftin
38 | remote_branch: gh-pages
39 | extra:
40 | generator: false
41 | exclude_docs: |
42 | gen_pages.py
43 | markdown_extensions:
44 | - toc:
45 | permalink: "#"
46 | - pymdownx.snippets:
47 | base_path:
48 | - !relative $config_dir
49 | - pymdownx.magiclink
50 | - attr_list
51 | - md_in_html
52 | - pymdownx.highlight:
53 | anchor_linenums: true
54 | - pymdownx.inlinehilite
55 | - pymdownx.superfences
56 | - markdown.extensions.attr_list
57 | - pymdownx.keys
58 | - pymdownx.tasklist
59 | - pymdownx.tilde
60 | - callouts
61 | - pymdownx.details
62 | - pymdownx.emoji
63 | - pymdownx.tabbed:
64 | alternate_style: true
65 | - mkdocs-click
66 | plugins:
67 | - search
68 | - markdown-exec
69 | - gen-files:
70 | scripts:
71 | - docs/gen_pages.py
72 | - literate-nav:
73 | nav_file: SUMMARY.md
74 | - section-index
75 | - mkdocstrings:
76 | handlers:
77 | python:
78 | import:
79 | - https://docs.python.org/3/objects.inv
80 | options:
81 | docstring_style: numpy
82 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | build-backend = "hatchling.build"
3 | requires = ["hatchling"]
4 |
5 | [project]
6 | authors = [
7 | {name = "Justin Flannery", email = "juftin@juftin.com"}
8 | ]
9 | classifiers = [
10 | "Development Status :: 3 - Alpha",
11 | "Framework :: Hatch",
12 | "Operating System :: OS Independent",
13 | "Programming Language :: Python",
14 | "Programming Language :: Python :: 3.8",
15 | "Programming Language :: Python :: 3.9",
16 | "Programming Language :: Python :: 3.10",
17 | "Programming Language :: Python :: 3.11",
18 | "Programming Language :: Python :: 3.12",
19 | "Programming Language :: Python :: Implementation :: CPython",
20 | "Programming Language :: Python :: Implementation :: PyPy"
21 | ]
22 | dependencies = [
23 | "hatch>=1.7.0,<2",
24 | "pip-tools>=6",
25 | "click",
26 | "rich"
27 | ]
28 | description = "hatch plugin to use pip-compile to manage project dependencies"
29 | dynamic = ["version"]
30 | license = "MIT"
31 | name = "hatch-pip-compile"
32 | readme = "README.md"
33 | requires-python = ">=3.8"
34 |
35 | [project.entry-points.hatch]
36 | hatch-pip-compile = "hatch_pip_compile.hooks"
37 |
38 | [project.scripts]
39 | hatch-pip-compile = "hatch_pip_compile.cli:cli"
40 |
41 | [project.urls]
42 | Documentation = "https://juftin.github.io/hatch-pip-compile"
43 | Issues = "https://juftin.github.io/hatch-pip-compile/issues"
44 | Source = "https://github.com/juftin/hatch-pip-compile"
45 |
46 | [tool.coverage.paths]
47 | hatch_pip_compile = ["hatch_pip_compile", "*/hatch-pip-compile/hatch_pip_compile"]
48 | tests = ["tests", "*/hatch-pip-compile/tests"]
49 |
50 | [tool.coverage.report]
51 | exclude_lines = [
52 | "no cov",
53 | "if __name__ == .__main__.:",
54 | "if TYPE_CHECKING:"
55 | ]
56 | show_missing = true
57 |
58 | [tool.coverage.run]
59 | branch = true
60 | disable_warnings = [
61 | "module-not-measured"
62 | ]
63 | omit = [
64 | "hatch_pip_compile/__about__.py",
65 | "hatch_pip_compile/hooks.py",
66 | "hatch_pip_compile/__main__.py"
67 | ]
68 | parallel = true
69 | source_pkgs = ["hatch_pip_compile", "tests"]
70 |
71 | [tool.hatch.env]
72 | requires = ["hatch-mkdocs"]
73 |
74 | [tool.hatch.env.collectors.mkdocs.docs]
75 | path = "mkdocs.yaml"
76 |
77 | [tool.hatch.envs.default]
78 | pip-compile-constraint = "default"
79 | post-install-commands = [
80 | "- pre-commit install"
81 | ]
82 | python = "3.11"
83 | type = "pip-compile"
84 |
85 | [tool.hatch.envs.default.scripts]
86 | cov = "hatch run test:cov {args:}"
87 | test = "hatch run test:test {args:}"
88 |
89 | [tool.hatch.envs.docs]
90 | detached = false
91 | type = "pip-compile"
92 |
93 | [tool.hatch.envs.gen]
94 | detached = true
95 |
96 | [tool.hatch.envs.gen.scripts]
97 | lock-all = "hatch env run --env default -- python -m hatch_pip_compile --all {args:}"
98 | release = [
99 | "npm install --prefix .github/semantic_release/",
100 | "npx --prefix .github/semantic_release/ semantic-release {args:}"
101 | ]
102 | upgrade-all = [
103 | "lock-all --upgrade"
104 | ]
105 |
106 | [tool.hatch.envs.lint]
107 | dependencies = [
108 | "mypy>=1.6.1",
109 | "ruff~=0.1.4"
110 | ]
111 | detached = true
112 | type = "pip-compile"
113 |
114 | [tool.hatch.envs.lint.scripts]
115 | all = [
116 | "style",
117 | "typing"
118 | ]
119 | fmt = [
120 | "ruff format {args:.}",
121 | "ruff --fix {args:.}",
122 | "style"
123 | ]
124 | precommit = [
125 | "pre-commit run --all-files"
126 | ]
127 | style = [
128 | "ruff {args:.}",
129 | "ruff format --check --diff {args:.}"
130 | ]
131 | typing = "mypy --install-types --non-interactive {args:hatch_pip_compile}"
132 |
133 | [tool.hatch.envs.matrix]
134 | template = "test"
135 |
136 | [[tool.hatch.envs.matrix.matrix]]
137 | python = ["3.8", "3.9", "3.10", "3.11", "3.12"]
138 |
139 | [tool.hatch.envs.test]
140 | dependencies = [
141 | "pytest",
142 | "pytest-cov",
143 | "tomlkit",
144 | "pytest-xdist"
145 | ]
146 |
147 | [tool.hatch.envs.test.scripts]
148 | cov = [
149 | "pytest --cov --cov-config=pyproject.toml --cov-report=xml --cov-report=term-missing {args: -n auto tests/ -vv}"
150 | ]
151 | test = [
152 | "pytest {args: -n auto tests/ -vv}"
153 | ]
154 |
155 | [tool.hatch.envs.versions]
156 | dependencies = []
157 | pip-compile-constraint = ""
158 | template = "test"
159 | type = "pip-compile"
160 |
161 | [[tool.hatch.envs.versions.matrix]]
162 | version = [
163 | "1.7.x",
164 | "1.8.x",
165 | "1.9.x",
166 | "1.10.x",
167 | "1.11.x",
168 | "1.12.x"
169 | ]
170 |
171 | [tool.hatch.envs.versions.overrides]
172 | matrix.version.dependencies = [
173 | "pytest",
174 | "pytest-cov",
175 | "tomlkit",
176 | "pytest-xdist",
177 | {value = "hatch~=1.7.0", if = ["1.7.x"]},
178 | {value = "hatch~=1.8.1", if = ["1.8.x"]},
179 | {value = "hatch~=1.9.7", if = ["1.9.x"]},
180 | {value = "hatch~=1.10.0", if = ["1.10.x"]},
181 | {value = "hatch~=1.11.1", if = ["1.11.x"]},
182 | {value = "hatch~=1.12.0", if = ["1.12.x"]}
183 | ]
184 |
185 | [tool.hatch.version]
186 | path = "hatch_pip_compile/__about__.py"
187 |
188 | [tool.mypy]
189 | ignore_missing_imports = true
190 |
191 | [tool.ruff]
192 | ignore = [
193 | # Allow non-abstract empty methods in abstract base classes
194 | "B027",
195 | # Boolean-typed positional argument in function definition
196 | "FBT001",
197 | # Boolean default positional argument in function definition
198 | "FBT002",
199 | # Allow boolean positional values in function calls, like `dict.get(... True)`
200 | "FBT003",
201 | # Ignore checks for possible passwords
202 | "S105",
203 | "S106",
204 | "S107",
205 | # Ignore complexity
206 | "C901",
207 | "PLR0911",
208 | "PLR0912",
209 | "PLR0913",
210 | "PLR0915",
211 | # Prefer `next(iter(mock_check_command.call_args))`
212 | "RUF015"
213 | ]
214 | line-length = 100
215 | select = [
216 | "A", # flake8-builtins
217 | "ARG", # flake8-unused-arguments
218 | "B", # flake8-bugbear
219 | "C", # mccabe
220 | "DTZ", # flake8-datetimez
221 | "E", # pycodestyle (Error)
222 | "EM", # flake8-errmsg
223 | "F", # Pyflakes
224 | "FBT", # flake8-boolean-trap
225 | "I", # isort
226 | "ICN", # flake8-import-conventions
227 | "N", # pep8-naming
228 | "PLC", # Pylint (Convention message)
229 | "PLE", # Pylint (Error message)
230 | "PLR", # Pylint (Refactor message)
231 | "PLW", # Pylint (Warning message)
232 | "Q", # flake8-quotes
233 | "RUF", # Ruff-specific rules
234 | "S", # flake8-bandit
235 | "T", # flake8-debugger (T10) and flake8-print (T20)
236 | "TID", # flake8-tidy-imports
237 | "UP", # pyupgrade
238 | "W", # pycodestyle (Warning)
239 | "YTT" # flake8-2020
240 | ]
241 | target-version = "py38"
242 |
243 | [tool.ruff.flake8-tidy-imports]
244 | ban-relative-imports = "all"
245 |
246 | [tool.ruff.isort]
247 | known-first-party = ["hatch_pip_compile"]
248 |
249 | [tool.ruff.per-file-ignores]
250 | # Tests can use magic values, assertions, relative imports, and unused arguments
251 | "tests/**/*" = ["PLR2004", "S101", "TID252", "ARG001"]
252 |
253 | [tool.ruff.pydocstyle]
254 | convention = "numpy"
255 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # - click
5 | # - hatch<2,>=1.7.0
6 | # - pip-tools>=6
7 | # - rich
8 | #
9 |
10 | anyio==4.4.0
11 | # via httpx
12 | backports-tarfile==1.2.0
13 | # via jaraco-context
14 | build==1.2.1
15 | # via pip-tools
16 | certifi==2024.7.4
17 | # via
18 | # httpcore
19 | # httpx
20 | click==8.1.7
21 | # via
22 | # hatch.envs.default
23 | # hatch
24 | # pip-tools
25 | # userpath
26 | distlib==0.3.8
27 | # via virtualenv
28 | filelock==3.15.4
29 | # via virtualenv
30 | h11==0.14.0
31 | # via httpcore
32 | hatch==1.12.0
33 | # via hatch.envs.default
34 | hatchling==1.25.0
35 | # via hatch
36 | httpcore==1.0.5
37 | # via httpx
38 | httpx==0.27.0
39 | # via hatch
40 | hyperlink==21.0.0
41 | # via hatch
42 | idna==3.7
43 | # via
44 | # anyio
45 | # httpx
46 | # hyperlink
47 | importlib-metadata==8.0.0
48 | # via keyring
49 | jaraco-classes==3.4.0
50 | # via keyring
51 | jaraco-context==5.3.0
52 | # via keyring
53 | jaraco-functools==4.0.1
54 | # via keyring
55 | keyring==25.2.1
56 | # via hatch
57 | markdown-it-py==3.0.0
58 | # via rich
59 | mdurl==0.1.2
60 | # via markdown-it-py
61 | more-itertools==10.3.0
62 | # via
63 | # jaraco-classes
64 | # jaraco-functools
65 | packaging==24.1
66 | # via
67 | # build
68 | # hatch
69 | # hatchling
70 | pathspec==0.12.1
71 | # via hatchling
72 | pexpect==4.9.0
73 | # via hatch
74 | pip-tools==7.4.1
75 | # via hatch.envs.default
76 | platformdirs==4.2.2
77 | # via
78 | # hatch
79 | # virtualenv
80 | pluggy==1.5.0
81 | # via hatchling
82 | ptyprocess==0.7.0
83 | # via pexpect
84 | pygments==2.18.0
85 | # via rich
86 | pyproject-hooks==1.1.0
87 | # via
88 | # build
89 | # pip-tools
90 | rich==13.7.1
91 | # via
92 | # hatch.envs.default
93 | # hatch
94 | shellingham==1.5.4
95 | # via hatch
96 | sniffio==1.3.1
97 | # via
98 | # anyio
99 | # httpx
100 | tomli-w==1.0.0
101 | # via hatch
102 | tomlkit==0.13.0
103 | # via hatch
104 | trove-classifiers==2024.7.2
105 | # via hatchling
106 | userpath==1.9.2
107 | # via hatch
108 | uv==0.2.24
109 | # via hatch
110 | virtualenv==20.26.3
111 | # via hatch
112 | wheel==0.43.0
113 | # via pip-tools
114 | zipp==3.19.2
115 | # via importlib-metadata
116 | zstandard==0.22.0
117 | # via hatch
118 |
119 | # The following packages are considered to be unsafe in a requirements file:
120 | # pip
121 | # setuptools
122 |
--------------------------------------------------------------------------------
/requirements/requirements-docs.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # [constraints] requirements.txt (SHA256: f944fb6ce9cada73ee126b3fa6f6999e1fb2e71c2fc2f9bc2efb209448582a3f)
5 | #
6 | # - markdown-callouts
7 | # - markdown-exec
8 | # - mkdocs
9 | # - mkdocs-click
10 | # - mkdocs-gen-files
11 | # - mkdocs-literate-nav
12 | # - mkdocs-material
13 | # - mkdocs-section-index
14 | # - mkdocstrings
15 | # - mkdocstrings-python
16 | # - pymdown-extensions
17 | # - click
18 | # - hatch<2,>=1.7.0
19 | # - pip-tools>=6
20 | # - rich
21 | #
22 |
23 | anyio==4.4.0
24 | # via
25 | # -c requirements.txt
26 | # httpx
27 | babel==2.15.0
28 | # via mkdocs-material
29 | backports-tarfile==1.2.0
30 | # via
31 | # -c requirements.txt
32 | # jaraco-context
33 | build==1.2.1
34 | # via
35 | # -c requirements.txt
36 | # pip-tools
37 | certifi==2024.7.4
38 | # via
39 | # -c requirements.txt
40 | # httpcore
41 | # httpx
42 | # requests
43 | charset-normalizer==3.3.2
44 | # via requests
45 | click==8.1.7
46 | # via
47 | # -c requirements.txt
48 | # hatch.envs.docs
49 | # hatch
50 | # mkdocs
51 | # mkdocs-click
52 | # mkdocstrings
53 | # pip-tools
54 | # userpath
55 | colorama==0.4.6
56 | # via
57 | # griffe
58 | # mkdocs-material
59 | distlib==0.3.8
60 | # via
61 | # -c requirements.txt
62 | # virtualenv
63 | filelock==3.15.4
64 | # via
65 | # -c requirements.txt
66 | # virtualenv
67 | ghp-import==2.1.0
68 | # via mkdocs
69 | griffe==0.47.0
70 | # via mkdocstrings-python
71 | h11==0.14.0
72 | # via
73 | # -c requirements.txt
74 | # httpcore
75 | hatch==1.12.0
76 | # via
77 | # -c requirements.txt
78 | # hatch.envs.docs
79 | hatchling==1.25.0
80 | # via
81 | # -c requirements.txt
82 | # hatch
83 | httpcore==1.0.5
84 | # via
85 | # -c requirements.txt
86 | # httpx
87 | httpx==0.27.0
88 | # via
89 | # -c requirements.txt
90 | # hatch
91 | hyperlink==21.0.0
92 | # via
93 | # -c requirements.txt
94 | # hatch
95 | idna==3.7
96 | # via
97 | # -c requirements.txt
98 | # anyio
99 | # httpx
100 | # hyperlink
101 | # requests
102 | importlib-metadata==8.0.0
103 | # via
104 | # -c requirements.txt
105 | # keyring
106 | jaraco-classes==3.4.0
107 | # via
108 | # -c requirements.txt
109 | # keyring
110 | jaraco-context==5.3.0
111 | # via
112 | # -c requirements.txt
113 | # keyring
114 | jaraco-functools==4.0.1
115 | # via
116 | # -c requirements.txt
117 | # keyring
118 | jinja2==3.1.4
119 | # via
120 | # mkdocs
121 | # mkdocs-material
122 | # mkdocstrings
123 | keyring==25.2.1
124 | # via
125 | # -c requirements.txt
126 | # hatch
127 | markdown==3.6
128 | # via
129 | # markdown-callouts
130 | # mkdocs
131 | # mkdocs-autorefs
132 | # mkdocs-click
133 | # mkdocs-material
134 | # mkdocstrings
135 | # pymdown-extensions
136 | markdown-callouts==0.4.0
137 | # via hatch.envs.docs
138 | markdown-exec==1.9.3
139 | # via hatch.envs.docs
140 | markdown-it-py==3.0.0
141 | # via
142 | # -c requirements.txt
143 | # rich
144 | markupsafe==2.1.5
145 | # via
146 | # jinja2
147 | # mkdocs
148 | # mkdocs-autorefs
149 | # mkdocstrings
150 | mdurl==0.1.2
151 | # via
152 | # -c requirements.txt
153 | # markdown-it-py
154 | mergedeep==1.3.4
155 | # via
156 | # mkdocs
157 | # mkdocs-get-deps
158 | mkdocs==1.6.0
159 | # via
160 | # hatch.envs.docs
161 | # mkdocs-autorefs
162 | # mkdocs-gen-files
163 | # mkdocs-literate-nav
164 | # mkdocs-material
165 | # mkdocs-section-index
166 | # mkdocstrings
167 | mkdocs-autorefs==1.0.1
168 | # via mkdocstrings
169 | mkdocs-click==0.8.1
170 | # via hatch.envs.docs
171 | mkdocs-gen-files==0.5.0
172 | # via hatch.envs.docs
173 | mkdocs-get-deps==0.2.0
174 | # via mkdocs
175 | mkdocs-literate-nav==0.6.1
176 | # via hatch.envs.docs
177 | mkdocs-material==9.5.28
178 | # via hatch.envs.docs
179 | mkdocs-material-extensions==1.3.1
180 | # via mkdocs-material
181 | mkdocs-section-index==0.3.9
182 | # via hatch.envs.docs
183 | mkdocstrings==0.25.1
184 | # via
185 | # hatch.envs.docs
186 | # mkdocstrings-python
187 | mkdocstrings-python==1.10.5
188 | # via hatch.envs.docs
189 | more-itertools==10.3.0
190 | # via
191 | # -c requirements.txt
192 | # jaraco-classes
193 | # jaraco-functools
194 | packaging==24.1
195 | # via
196 | # -c requirements.txt
197 | # build
198 | # hatch
199 | # hatchling
200 | # mkdocs
201 | paginate==0.5.6
202 | # via mkdocs-material
203 | pathspec==0.12.1
204 | # via
205 | # -c requirements.txt
206 | # hatchling
207 | # mkdocs
208 | pexpect==4.9.0
209 | # via
210 | # -c requirements.txt
211 | # hatch
212 | pip-tools==7.4.1
213 | # via
214 | # -c requirements.txt
215 | # hatch.envs.docs
216 | platformdirs==4.2.2
217 | # via
218 | # -c requirements.txt
219 | # hatch
220 | # mkdocs-get-deps
221 | # mkdocstrings
222 | # virtualenv
223 | pluggy==1.5.0
224 | # via
225 | # -c requirements.txt
226 | # hatchling
227 | ptyprocess==0.7.0
228 | # via
229 | # -c requirements.txt
230 | # pexpect
231 | pygments==2.18.0
232 | # via
233 | # -c requirements.txt
234 | # mkdocs-material
235 | # rich
236 | pymdown-extensions==10.8.1
237 | # via
238 | # hatch.envs.docs
239 | # markdown-exec
240 | # mkdocs-material
241 | # mkdocstrings
242 | pyproject-hooks==1.1.0
243 | # via
244 | # -c requirements.txt
245 | # build
246 | # pip-tools
247 | python-dateutil==2.9.0.post0
248 | # via ghp-import
249 | pyyaml==6.0.1
250 | # via
251 | # mkdocs
252 | # mkdocs-get-deps
253 | # pymdown-extensions
254 | # pyyaml-env-tag
255 | pyyaml-env-tag==0.1
256 | # via mkdocs
257 | regex==2024.5.15
258 | # via mkdocs-material
259 | requests==2.32.3
260 | # via mkdocs-material
261 | rich==13.7.1
262 | # via
263 | # -c requirements.txt
264 | # hatch.envs.docs
265 | # hatch
266 | shellingham==1.5.4
267 | # via
268 | # -c requirements.txt
269 | # hatch
270 | six==1.16.0
271 | # via python-dateutil
272 | sniffio==1.3.1
273 | # via
274 | # -c requirements.txt
275 | # anyio
276 | # httpx
277 | tomli-w==1.0.0
278 | # via
279 | # -c requirements.txt
280 | # hatch
281 | tomlkit==0.13.0
282 | # via
283 | # -c requirements.txt
284 | # hatch
285 | trove-classifiers==2024.7.2
286 | # via
287 | # -c requirements.txt
288 | # hatchling
289 | urllib3==2.2.2
290 | # via requests
291 | userpath==1.9.2
292 | # via
293 | # -c requirements.txt
294 | # hatch
295 | uv==0.2.24
296 | # via
297 | # -c requirements.txt
298 | # hatch
299 | virtualenv==20.26.3
300 | # via
301 | # -c requirements.txt
302 | # hatch
303 | watchdog==4.0.1
304 | # via mkdocs
305 | wheel==0.43.0
306 | # via
307 | # -c requirements.txt
308 | # pip-tools
309 | zipp==3.19.2
310 | # via
311 | # -c requirements.txt
312 | # importlib-metadata
313 | zstandard==0.22.0
314 | # via
315 | # -c requirements.txt
316 | # hatch
317 |
318 | # The following packages are considered to be unsafe in a requirements file:
319 | # pip
320 | # setuptools
321 |
--------------------------------------------------------------------------------
/requirements/requirements-lint.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # - mypy>=1.6.1
5 | # - ruff~=0.1.4
6 | #
7 |
8 | mypy==1.10.1
9 | # via hatch.envs.lint
10 | mypy-extensions==1.0.0
11 | # via mypy
12 | ruff==0.1.15
13 | # via hatch.envs.lint
14 | typing-extensions==4.12.2
15 | # via mypy
16 |
--------------------------------------------------------------------------------
/requirements/requirements-matrix.py3.10.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.10
3 | #
4 | # [constraints] requirements.txt (SHA256: f944fb6ce9cada73ee126b3fa6f6999e1fb2e71c2fc2f9bc2efb209448582a3f)
5 | #
6 | # - pytest
7 | # - pytest-cov
8 | # - tomlkit
9 | # - pytest-xdist
10 | # - click
11 | # - hatch<2,>=1.7.0
12 | # - pip-tools>=6
13 | # - rich
14 | #
15 |
16 | anyio==4.4.0
17 | # via
18 | # -c requirements.txt
19 | # httpx
20 | backports-tarfile==1.2.0
21 | # via
22 | # -c requirements.txt
23 | # jaraco-context
24 | build==1.2.1
25 | # via
26 | # -c requirements.txt
27 | # pip-tools
28 | certifi==2024.7.4
29 | # via
30 | # -c requirements.txt
31 | # httpcore
32 | # httpx
33 | click==8.1.7
34 | # via
35 | # -c requirements.txt
36 | # hatch.envs.matrix.py3.10
37 | # hatch
38 | # pip-tools
39 | # userpath
40 | coverage==7.6.0
41 | # via pytest-cov
42 | distlib==0.3.8
43 | # via
44 | # -c requirements.txt
45 | # virtualenv
46 | exceptiongroup==1.2.2
47 | # via
48 | # anyio
49 | # pytest
50 | execnet==2.1.1
51 | # via pytest-xdist
52 | filelock==3.15.4
53 | # via
54 | # -c requirements.txt
55 | # virtualenv
56 | h11==0.14.0
57 | # via
58 | # -c requirements.txt
59 | # httpcore
60 | hatch==1.12.0
61 | # via
62 | # -c requirements.txt
63 | # hatch.envs.matrix.py3.10
64 | hatchling==1.25.0
65 | # via
66 | # -c requirements.txt
67 | # hatch
68 | httpcore==1.0.5
69 | # via
70 | # -c requirements.txt
71 | # httpx
72 | httpx==0.27.0
73 | # via
74 | # -c requirements.txt
75 | # hatch
76 | hyperlink==21.0.0
77 | # via
78 | # -c requirements.txt
79 | # hatch
80 | idna==3.7
81 | # via
82 | # -c requirements.txt
83 | # anyio
84 | # httpx
85 | # hyperlink
86 | importlib-metadata==8.0.0
87 | # via
88 | # -c requirements.txt
89 | # keyring
90 | iniconfig==2.0.0
91 | # via pytest
92 | jaraco-classes==3.4.0
93 | # via
94 | # -c requirements.txt
95 | # keyring
96 | jaraco-context==5.3.0
97 | # via
98 | # -c requirements.txt
99 | # keyring
100 | jaraco-functools==4.0.1
101 | # via
102 | # -c requirements.txt
103 | # keyring
104 | keyring==25.2.1
105 | # via
106 | # -c requirements.txt
107 | # hatch
108 | markdown-it-py==3.0.0
109 | # via
110 | # -c requirements.txt
111 | # rich
112 | mdurl==0.1.2
113 | # via
114 | # -c requirements.txt
115 | # markdown-it-py
116 | more-itertools==10.3.0
117 | # via
118 | # -c requirements.txt
119 | # jaraco-classes
120 | # jaraco-functools
121 | packaging==24.1
122 | # via
123 | # -c requirements.txt
124 | # build
125 | # hatch
126 | # hatchling
127 | # pytest
128 | pathspec==0.12.1
129 | # via
130 | # -c requirements.txt
131 | # hatchling
132 | pexpect==4.9.0
133 | # via
134 | # -c requirements.txt
135 | # hatch
136 | pip-tools==7.4.1
137 | # via
138 | # -c requirements.txt
139 | # hatch.envs.matrix.py3.10
140 | platformdirs==4.2.2
141 | # via
142 | # -c requirements.txt
143 | # hatch
144 | # virtualenv
145 | pluggy==1.5.0
146 | # via
147 | # -c requirements.txt
148 | # hatchling
149 | # pytest
150 | ptyprocess==0.7.0
151 | # via
152 | # -c requirements.txt
153 | # pexpect
154 | pygments==2.18.0
155 | # via
156 | # -c requirements.txt
157 | # rich
158 | pyproject-hooks==1.1.0
159 | # via
160 | # -c requirements.txt
161 | # build
162 | # pip-tools
163 | pytest==8.2.2
164 | # via
165 | # hatch.envs.matrix.py3.10
166 | # pytest-cov
167 | # pytest-xdist
168 | pytest-cov==5.0.0
169 | # via hatch.envs.matrix.py3.10
170 | pytest-xdist==3.6.1
171 | # via hatch.envs.matrix.py3.10
172 | rich==13.7.1
173 | # via
174 | # -c requirements.txt
175 | # hatch.envs.matrix.py3.10
176 | # hatch
177 | shellingham==1.5.4
178 | # via
179 | # -c requirements.txt
180 | # hatch
181 | sniffio==1.3.1
182 | # via
183 | # -c requirements.txt
184 | # anyio
185 | # httpx
186 | tomli==2.0.1
187 | # via
188 | # build
189 | # coverage
190 | # hatchling
191 | # pip-tools
192 | # pytest
193 | tomli-w==1.0.0
194 | # via
195 | # -c requirements.txt
196 | # hatch
197 | tomlkit==0.13.0
198 | # via
199 | # -c requirements.txt
200 | # hatch.envs.matrix.py3.10
201 | # hatch
202 | trove-classifiers==2024.7.2
203 | # via
204 | # -c requirements.txt
205 | # hatchling
206 | typing-extensions==4.12.2
207 | # via anyio
208 | userpath==1.9.2
209 | # via
210 | # -c requirements.txt
211 | # hatch
212 | uv==0.2.24
213 | # via
214 | # -c requirements.txt
215 | # hatch
216 | virtualenv==20.26.3
217 | # via
218 | # -c requirements.txt
219 | # hatch
220 | wheel==0.43.0
221 | # via
222 | # -c requirements.txt
223 | # pip-tools
224 | zipp==3.19.2
225 | # via
226 | # -c requirements.txt
227 | # importlib-metadata
228 | zstandard==0.22.0
229 | # via
230 | # -c requirements.txt
231 | # hatch
232 |
233 | # The following packages are considered to be unsafe in a requirements file:
234 | # pip
235 | # setuptools
236 |
--------------------------------------------------------------------------------
/requirements/requirements-matrix.py3.11.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # [constraints] requirements.txt (SHA256: f944fb6ce9cada73ee126b3fa6f6999e1fb2e71c2fc2f9bc2efb209448582a3f)
5 | #
6 | # - pytest
7 | # - pytest-cov
8 | # - tomlkit
9 | # - pytest-xdist
10 | # - click
11 | # - hatch<2,>=1.7.0
12 | # - pip-tools>=6
13 | # - rich
14 | #
15 |
16 | anyio==4.4.0
17 | # via
18 | # -c requirements.txt
19 | # httpx
20 | backports-tarfile==1.2.0
21 | # via
22 | # -c requirements.txt
23 | # jaraco-context
24 | build==1.2.1
25 | # via
26 | # -c requirements.txt
27 | # pip-tools
28 | certifi==2024.7.4
29 | # via
30 | # -c requirements.txt
31 | # httpcore
32 | # httpx
33 | click==8.1.7
34 | # via
35 | # -c requirements.txt
36 | # hatch.envs.matrix.py3.11
37 | # hatch
38 | # pip-tools
39 | # userpath
40 | coverage==7.6.0
41 | # via pytest-cov
42 | distlib==0.3.8
43 | # via
44 | # -c requirements.txt
45 | # virtualenv
46 | execnet==2.1.1
47 | # via pytest-xdist
48 | filelock==3.15.4
49 | # via
50 | # -c requirements.txt
51 | # virtualenv
52 | h11==0.14.0
53 | # via
54 | # -c requirements.txt
55 | # httpcore
56 | hatch==1.12.0
57 | # via
58 | # -c requirements.txt
59 | # hatch.envs.matrix.py3.11
60 | hatchling==1.25.0
61 | # via
62 | # -c requirements.txt
63 | # hatch
64 | httpcore==1.0.5
65 | # via
66 | # -c requirements.txt
67 | # httpx
68 | httpx==0.27.0
69 | # via
70 | # -c requirements.txt
71 | # hatch
72 | hyperlink==21.0.0
73 | # via
74 | # -c requirements.txt
75 | # hatch
76 | idna==3.7
77 | # via
78 | # -c requirements.txt
79 | # anyio
80 | # httpx
81 | # hyperlink
82 | importlib-metadata==8.0.0
83 | # via
84 | # -c requirements.txt
85 | # keyring
86 | iniconfig==2.0.0
87 | # via pytest
88 | jaraco-classes==3.4.0
89 | # via
90 | # -c requirements.txt
91 | # keyring
92 | jaraco-context==5.3.0
93 | # via
94 | # -c requirements.txt
95 | # keyring
96 | jaraco-functools==4.0.1
97 | # via
98 | # -c requirements.txt
99 | # keyring
100 | keyring==25.2.1
101 | # via
102 | # -c requirements.txt
103 | # hatch
104 | markdown-it-py==3.0.0
105 | # via
106 | # -c requirements.txt
107 | # rich
108 | mdurl==0.1.2
109 | # via
110 | # -c requirements.txt
111 | # markdown-it-py
112 | more-itertools==10.3.0
113 | # via
114 | # -c requirements.txt
115 | # jaraco-classes
116 | # jaraco-functools
117 | packaging==24.1
118 | # via
119 | # -c requirements.txt
120 | # build
121 | # hatch
122 | # hatchling
123 | # pytest
124 | pathspec==0.12.1
125 | # via
126 | # -c requirements.txt
127 | # hatchling
128 | pexpect==4.9.0
129 | # via
130 | # -c requirements.txt
131 | # hatch
132 | pip-tools==7.4.1
133 | # via
134 | # -c requirements.txt
135 | # hatch.envs.matrix.py3.11
136 | platformdirs==4.2.2
137 | # via
138 | # -c requirements.txt
139 | # hatch
140 | # virtualenv
141 | pluggy==1.5.0
142 | # via
143 | # -c requirements.txt
144 | # hatchling
145 | # pytest
146 | ptyprocess==0.7.0
147 | # via
148 | # -c requirements.txt
149 | # pexpect
150 | pygments==2.18.0
151 | # via
152 | # -c requirements.txt
153 | # rich
154 | pyproject-hooks==1.1.0
155 | # via
156 | # -c requirements.txt
157 | # build
158 | # pip-tools
159 | pytest==8.2.2
160 | # via
161 | # hatch.envs.matrix.py3.11
162 | # pytest-cov
163 | # pytest-xdist
164 | pytest-cov==5.0.0
165 | # via hatch.envs.matrix.py3.11
166 | pytest-xdist==3.6.1
167 | # via hatch.envs.matrix.py3.11
168 | rich==13.7.1
169 | # via
170 | # -c requirements.txt
171 | # hatch.envs.matrix.py3.11
172 | # hatch
173 | shellingham==1.5.4
174 | # via
175 | # -c requirements.txt
176 | # hatch
177 | sniffio==1.3.1
178 | # via
179 | # -c requirements.txt
180 | # anyio
181 | # httpx
182 | tomli-w==1.0.0
183 | # via
184 | # -c requirements.txt
185 | # hatch
186 | tomlkit==0.13.0
187 | # via
188 | # -c requirements.txt
189 | # hatch.envs.matrix.py3.11
190 | # hatch
191 | trove-classifiers==2024.7.2
192 | # via
193 | # -c requirements.txt
194 | # hatchling
195 | userpath==1.9.2
196 | # via
197 | # -c requirements.txt
198 | # hatch
199 | uv==0.2.24
200 | # via
201 | # -c requirements.txt
202 | # hatch
203 | virtualenv==20.26.3
204 | # via
205 | # -c requirements.txt
206 | # hatch
207 | wheel==0.43.0
208 | # via
209 | # -c requirements.txt
210 | # pip-tools
211 | zipp==3.19.2
212 | # via
213 | # -c requirements.txt
214 | # importlib-metadata
215 | zstandard==0.22.0
216 | # via
217 | # -c requirements.txt
218 | # hatch
219 |
220 | # The following packages are considered to be unsafe in a requirements file:
221 | # pip
222 | # setuptools
223 |
--------------------------------------------------------------------------------
/requirements/requirements-matrix.py3.12.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.12
3 | #
4 | # [constraints] requirements.txt (SHA256: f944fb6ce9cada73ee126b3fa6f6999e1fb2e71c2fc2f9bc2efb209448582a3f)
5 | #
6 | # - pytest
7 | # - pytest-cov
8 | # - tomlkit
9 | # - pytest-xdist
10 | # - click
11 | # - hatch<2,>=1.7.0
12 | # - pip-tools>=6
13 | # - rich
14 | #
15 |
16 | anyio==4.4.0
17 | # via
18 | # -c requirements.txt
19 | # httpx
20 | build==1.2.1
21 | # via
22 | # -c requirements.txt
23 | # pip-tools
24 | certifi==2024.7.4
25 | # via
26 | # -c requirements.txt
27 | # httpcore
28 | # httpx
29 | click==8.1.7
30 | # via
31 | # -c requirements.txt
32 | # hatch.envs.matrix.py3.12
33 | # hatch
34 | # pip-tools
35 | # userpath
36 | coverage==7.6.0
37 | # via pytest-cov
38 | distlib==0.3.8
39 | # via
40 | # -c requirements.txt
41 | # virtualenv
42 | execnet==2.1.1
43 | # via pytest-xdist
44 | filelock==3.15.4
45 | # via
46 | # -c requirements.txt
47 | # virtualenv
48 | h11==0.14.0
49 | # via
50 | # -c requirements.txt
51 | # httpcore
52 | hatch==1.12.0
53 | # via
54 | # -c requirements.txt
55 | # hatch.envs.matrix.py3.12
56 | hatchling==1.25.0
57 | # via
58 | # -c requirements.txt
59 | # hatch
60 | httpcore==1.0.5
61 | # via
62 | # -c requirements.txt
63 | # httpx
64 | httpx==0.27.0
65 | # via
66 | # -c requirements.txt
67 | # hatch
68 | hyperlink==21.0.0
69 | # via
70 | # -c requirements.txt
71 | # hatch
72 | idna==3.7
73 | # via
74 | # -c requirements.txt
75 | # anyio
76 | # httpx
77 | # hyperlink
78 | iniconfig==2.0.0
79 | # via pytest
80 | jaraco-classes==3.4.0
81 | # via
82 | # -c requirements.txt
83 | # keyring
84 | jaraco-context==5.3.0
85 | # via
86 | # -c requirements.txt
87 | # keyring
88 | jaraco-functools==4.0.1
89 | # via
90 | # -c requirements.txt
91 | # keyring
92 | keyring==25.2.1
93 | # via
94 | # -c requirements.txt
95 | # hatch
96 | markdown-it-py==3.0.0
97 | # via
98 | # -c requirements.txt
99 | # rich
100 | mdurl==0.1.2
101 | # via
102 | # -c requirements.txt
103 | # markdown-it-py
104 | more-itertools==10.3.0
105 | # via
106 | # -c requirements.txt
107 | # jaraco-classes
108 | # jaraco-functools
109 | packaging==24.1
110 | # via
111 | # -c requirements.txt
112 | # build
113 | # hatch
114 | # hatchling
115 | # pytest
116 | pathspec==0.12.1
117 | # via
118 | # -c requirements.txt
119 | # hatchling
120 | pexpect==4.9.0
121 | # via
122 | # -c requirements.txt
123 | # hatch
124 | pip-tools==7.4.1
125 | # via
126 | # -c requirements.txt
127 | # hatch.envs.matrix.py3.12
128 | platformdirs==4.2.2
129 | # via
130 | # -c requirements.txt
131 | # hatch
132 | # virtualenv
133 | pluggy==1.5.0
134 | # via
135 | # -c requirements.txt
136 | # hatchling
137 | # pytest
138 | ptyprocess==0.7.0
139 | # via
140 | # -c requirements.txt
141 | # pexpect
142 | pygments==2.18.0
143 | # via
144 | # -c requirements.txt
145 | # rich
146 | pyproject-hooks==1.1.0
147 | # via
148 | # -c requirements.txt
149 | # build
150 | # pip-tools
151 | pytest==8.2.2
152 | # via
153 | # hatch.envs.matrix.py3.12
154 | # pytest-cov
155 | # pytest-xdist
156 | pytest-cov==5.0.0
157 | # via hatch.envs.matrix.py3.12
158 | pytest-xdist==3.6.1
159 | # via hatch.envs.matrix.py3.12
160 | rich==13.7.1
161 | # via
162 | # -c requirements.txt
163 | # hatch.envs.matrix.py3.12
164 | # hatch
165 | shellingham==1.5.4
166 | # via
167 | # -c requirements.txt
168 | # hatch
169 | sniffio==1.3.1
170 | # via
171 | # -c requirements.txt
172 | # anyio
173 | # httpx
174 | tomli-w==1.0.0
175 | # via
176 | # -c requirements.txt
177 | # hatch
178 | tomlkit==0.13.0
179 | # via
180 | # -c requirements.txt
181 | # hatch.envs.matrix.py3.12
182 | # hatch
183 | trove-classifiers==2024.7.2
184 | # via
185 | # -c requirements.txt
186 | # hatchling
187 | userpath==1.9.2
188 | # via
189 | # -c requirements.txt
190 | # hatch
191 | uv==0.2.24
192 | # via
193 | # -c requirements.txt
194 | # hatch
195 | virtualenv==20.26.3
196 | # via
197 | # -c requirements.txt
198 | # hatch
199 | wheel==0.43.0
200 | # via
201 | # -c requirements.txt
202 | # pip-tools
203 | zstandard==0.22.0
204 | # via
205 | # -c requirements.txt
206 | # hatch
207 |
208 | # The following packages are considered to be unsafe in a requirements file:
209 | # pip
210 | # setuptools
211 |
--------------------------------------------------------------------------------
/requirements/requirements-matrix.py3.8.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.8
3 | #
4 | # [constraints] requirements.txt (SHA256: f944fb6ce9cada73ee126b3fa6f6999e1fb2e71c2fc2f9bc2efb209448582a3f)
5 | #
6 | # - pytest
7 | # - pytest-cov
8 | # - tomlkit
9 | # - pytest-xdist
10 | # - click
11 | # - hatch<2,>=1.7.0
12 | # - pip-tools>=6
13 | # - rich
14 | #
15 |
16 | anyio==4.4.0
17 | # via
18 | # -c requirements.txt
19 | # httpx
20 | backports-tarfile==1.2.0
21 | # via
22 | # -c requirements.txt
23 | # jaraco-context
24 | build==1.2.1
25 | # via
26 | # -c requirements.txt
27 | # pip-tools
28 | certifi==2024.7.4
29 | # via
30 | # -c requirements.txt
31 | # httpcore
32 | # httpx
33 | click==8.1.7
34 | # via
35 | # -c requirements.txt
36 | # hatch.envs.matrix.py3.8
37 | # hatch
38 | # pip-tools
39 | # userpath
40 | coverage==7.6.0
41 | # via pytest-cov
42 | distlib==0.3.8
43 | # via
44 | # -c requirements.txt
45 | # virtualenv
46 | exceptiongroup==1.2.2
47 | # via
48 | # anyio
49 | # pytest
50 | execnet==2.1.1
51 | # via pytest-xdist
52 | filelock==3.15.4
53 | # via
54 | # -c requirements.txt
55 | # virtualenv
56 | h11==0.14.0
57 | # via
58 | # -c requirements.txt
59 | # httpcore
60 | hatch==1.12.0
61 | # via
62 | # -c requirements.txt
63 | # hatch.envs.matrix.py3.8
64 | hatchling==1.25.0
65 | # via
66 | # -c requirements.txt
67 | # hatch
68 | httpcore==1.0.5
69 | # via
70 | # -c requirements.txt
71 | # httpx
72 | httpx==0.27.0
73 | # via
74 | # -c requirements.txt
75 | # hatch
76 | hyperlink==21.0.0
77 | # via
78 | # -c requirements.txt
79 | # hatch
80 | idna==3.7
81 | # via
82 | # -c requirements.txt
83 | # anyio
84 | # httpx
85 | # hyperlink
86 | importlib-metadata==8.0.0
87 | # via
88 | # -c requirements.txt
89 | # build
90 | # keyring
91 | importlib-resources==6.4.0
92 | # via keyring
93 | iniconfig==2.0.0
94 | # via pytest
95 | jaraco-classes==3.4.0
96 | # via
97 | # -c requirements.txt
98 | # keyring
99 | jaraco-context==5.3.0
100 | # via
101 | # -c requirements.txt
102 | # keyring
103 | jaraco-functools==4.0.1
104 | # via
105 | # -c requirements.txt
106 | # keyring
107 | keyring==25.2.1
108 | # via
109 | # -c requirements.txt
110 | # hatch
111 | markdown-it-py==3.0.0
112 | # via
113 | # -c requirements.txt
114 | # rich
115 | mdurl==0.1.2
116 | # via
117 | # -c requirements.txt
118 | # markdown-it-py
119 | more-itertools==10.3.0
120 | # via
121 | # -c requirements.txt
122 | # jaraco-classes
123 | # jaraco-functools
124 | packaging==24.1
125 | # via
126 | # -c requirements.txt
127 | # build
128 | # hatch
129 | # hatchling
130 | # pytest
131 | pathspec==0.12.1
132 | # via
133 | # -c requirements.txt
134 | # hatchling
135 | pexpect==4.9.0
136 | # via
137 | # -c requirements.txt
138 | # hatch
139 | pip-tools==7.4.1
140 | # via
141 | # -c requirements.txt
142 | # hatch.envs.matrix.py3.8
143 | platformdirs==4.2.2
144 | # via
145 | # -c requirements.txt
146 | # hatch
147 | # virtualenv
148 | pluggy==1.5.0
149 | # via
150 | # -c requirements.txt
151 | # hatchling
152 | # pytest
153 | ptyprocess==0.7.0
154 | # via
155 | # -c requirements.txt
156 | # pexpect
157 | pygments==2.18.0
158 | # via
159 | # -c requirements.txt
160 | # rich
161 | pyproject-hooks==1.1.0
162 | # via
163 | # -c requirements.txt
164 | # build
165 | # pip-tools
166 | pytest==8.2.2
167 | # via
168 | # hatch.envs.matrix.py3.8
169 | # pytest-cov
170 | # pytest-xdist
171 | pytest-cov==5.0.0
172 | # via hatch.envs.matrix.py3.8
173 | pytest-xdist==3.6.1
174 | # via hatch.envs.matrix.py3.8
175 | rich==13.7.1
176 | # via
177 | # -c requirements.txt
178 | # hatch.envs.matrix.py3.8
179 | # hatch
180 | shellingham==1.5.4
181 | # via
182 | # -c requirements.txt
183 | # hatch
184 | sniffio==1.3.1
185 | # via
186 | # -c requirements.txt
187 | # anyio
188 | # httpx
189 | tomli==2.0.1
190 | # via
191 | # build
192 | # coverage
193 | # hatchling
194 | # pip-tools
195 | # pytest
196 | tomli-w==1.0.0
197 | # via
198 | # -c requirements.txt
199 | # hatch
200 | tomlkit==0.13.0
201 | # via
202 | # -c requirements.txt
203 | # hatch.envs.matrix.py3.8
204 | # hatch
205 | trove-classifiers==2024.7.2
206 | # via
207 | # -c requirements.txt
208 | # hatchling
209 | typing-extensions==4.12.2
210 | # via
211 | # anyio
212 | # rich
213 | userpath==1.9.2
214 | # via
215 | # -c requirements.txt
216 | # hatch
217 | uv==0.2.24
218 | # via
219 | # -c requirements.txt
220 | # hatch
221 | virtualenv==20.26.3
222 | # via
223 | # -c requirements.txt
224 | # hatch
225 | wheel==0.43.0
226 | # via
227 | # -c requirements.txt
228 | # pip-tools
229 | zipp==3.19.2
230 | # via
231 | # -c requirements.txt
232 | # importlib-metadata
233 | # importlib-resources
234 | zstandard==0.22.0
235 | # via
236 | # -c requirements.txt
237 | # hatch
238 |
239 | # The following packages are considered to be unsafe in a requirements file:
240 | # pip
241 | # setuptools
242 |
--------------------------------------------------------------------------------
/requirements/requirements-matrix.py3.9.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.9
3 | #
4 | # [constraints] requirements.txt (SHA256: f944fb6ce9cada73ee126b3fa6f6999e1fb2e71c2fc2f9bc2efb209448582a3f)
5 | #
6 | # - pytest
7 | # - pytest-cov
8 | # - tomlkit
9 | # - pytest-xdist
10 | # - click
11 | # - hatch<2,>=1.7.0
12 | # - pip-tools>=6
13 | # - rich
14 | #
15 |
16 | anyio==4.4.0
17 | # via
18 | # -c requirements.txt
19 | # httpx
20 | backports-tarfile==1.2.0
21 | # via
22 | # -c requirements.txt
23 | # jaraco-context
24 | build==1.2.1
25 | # via
26 | # -c requirements.txt
27 | # pip-tools
28 | certifi==2024.7.4
29 | # via
30 | # -c requirements.txt
31 | # httpcore
32 | # httpx
33 | click==8.1.7
34 | # via
35 | # -c requirements.txt
36 | # hatch.envs.matrix.py3.9
37 | # hatch
38 | # pip-tools
39 | # userpath
40 | coverage==7.6.0
41 | # via pytest-cov
42 | distlib==0.3.8
43 | # via
44 | # -c requirements.txt
45 | # virtualenv
46 | exceptiongroup==1.2.2
47 | # via
48 | # anyio
49 | # pytest
50 | execnet==2.1.1
51 | # via pytest-xdist
52 | filelock==3.15.4
53 | # via
54 | # -c requirements.txt
55 | # virtualenv
56 | h11==0.14.0
57 | # via
58 | # -c requirements.txt
59 | # httpcore
60 | hatch==1.12.0
61 | # via
62 | # -c requirements.txt
63 | # hatch.envs.matrix.py3.9
64 | hatchling==1.25.0
65 | # via
66 | # -c requirements.txt
67 | # hatch
68 | httpcore==1.0.5
69 | # via
70 | # -c requirements.txt
71 | # httpx
72 | httpx==0.27.0
73 | # via
74 | # -c requirements.txt
75 | # hatch
76 | hyperlink==21.0.0
77 | # via
78 | # -c requirements.txt
79 | # hatch
80 | idna==3.7
81 | # via
82 | # -c requirements.txt
83 | # anyio
84 | # httpx
85 | # hyperlink
86 | importlib-metadata==8.0.0
87 | # via
88 | # -c requirements.txt
89 | # build
90 | # keyring
91 | iniconfig==2.0.0
92 | # via pytest
93 | jaraco-classes==3.4.0
94 | # via
95 | # -c requirements.txt
96 | # keyring
97 | jaraco-context==5.3.0
98 | # via
99 | # -c requirements.txt
100 | # keyring
101 | jaraco-functools==4.0.1
102 | # via
103 | # -c requirements.txt
104 | # keyring
105 | keyring==25.2.1
106 | # via
107 | # -c requirements.txt
108 | # hatch
109 | markdown-it-py==3.0.0
110 | # via
111 | # -c requirements.txt
112 | # rich
113 | mdurl==0.1.2
114 | # via
115 | # -c requirements.txt
116 | # markdown-it-py
117 | more-itertools==10.3.0
118 | # via
119 | # -c requirements.txt
120 | # jaraco-classes
121 | # jaraco-functools
122 | packaging==24.1
123 | # via
124 | # -c requirements.txt
125 | # build
126 | # hatch
127 | # hatchling
128 | # pytest
129 | pathspec==0.12.1
130 | # via
131 | # -c requirements.txt
132 | # hatchling
133 | pexpect==4.9.0
134 | # via
135 | # -c requirements.txt
136 | # hatch
137 | pip-tools==7.4.1
138 | # via
139 | # -c requirements.txt
140 | # hatch.envs.matrix.py3.9
141 | platformdirs==4.2.2
142 | # via
143 | # -c requirements.txt
144 | # hatch
145 | # virtualenv
146 | pluggy==1.5.0
147 | # via
148 | # -c requirements.txt
149 | # hatchling
150 | # pytest
151 | ptyprocess==0.7.0
152 | # via
153 | # -c requirements.txt
154 | # pexpect
155 | pygments==2.18.0
156 | # via
157 | # -c requirements.txt
158 | # rich
159 | pyproject-hooks==1.1.0
160 | # via
161 | # -c requirements.txt
162 | # build
163 | # pip-tools
164 | pytest==8.2.2
165 | # via
166 | # hatch.envs.matrix.py3.9
167 | # pytest-cov
168 | # pytest-xdist
169 | pytest-cov==5.0.0
170 | # via hatch.envs.matrix.py3.9
171 | pytest-xdist==3.6.1
172 | # via hatch.envs.matrix.py3.9
173 | rich==13.7.1
174 | # via
175 | # -c requirements.txt
176 | # hatch.envs.matrix.py3.9
177 | # hatch
178 | shellingham==1.5.4
179 | # via
180 | # -c requirements.txt
181 | # hatch
182 | sniffio==1.3.1
183 | # via
184 | # -c requirements.txt
185 | # anyio
186 | # httpx
187 | tomli==2.0.1
188 | # via
189 | # build
190 | # coverage
191 | # hatchling
192 | # pip-tools
193 | # pytest
194 | tomli-w==1.0.0
195 | # via
196 | # -c requirements.txt
197 | # hatch
198 | tomlkit==0.13.0
199 | # via
200 | # -c requirements.txt
201 | # hatch.envs.matrix.py3.9
202 | # hatch
203 | trove-classifiers==2024.7.2
204 | # via
205 | # -c requirements.txt
206 | # hatchling
207 | typing-extensions==4.12.2
208 | # via anyio
209 | userpath==1.9.2
210 | # via
211 | # -c requirements.txt
212 | # hatch
213 | uv==0.2.24
214 | # via
215 | # -c requirements.txt
216 | # hatch
217 | virtualenv==20.26.3
218 | # via
219 | # -c requirements.txt
220 | # hatch
221 | wheel==0.43.0
222 | # via
223 | # -c requirements.txt
224 | # pip-tools
225 | zipp==3.19.2
226 | # via
227 | # -c requirements.txt
228 | # importlib-metadata
229 | zstandard==0.22.0
230 | # via
231 | # -c requirements.txt
232 | # hatch
233 |
234 | # The following packages are considered to be unsafe in a requirements file:
235 | # pip
236 | # setuptools
237 |
--------------------------------------------------------------------------------
/requirements/requirements-test.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # [constraints] requirements.txt (SHA256: f944fb6ce9cada73ee126b3fa6f6999e1fb2e71c2fc2f9bc2efb209448582a3f)
5 | #
6 | # - pytest
7 | # - pytest-cov
8 | # - tomlkit
9 | # - pytest-xdist
10 | # - click
11 | # - hatch<2,>=1.7.0
12 | # - pip-tools>=6
13 | # - rich
14 | #
15 |
16 | anyio==4.4.0
17 | # via
18 | # -c requirements.txt
19 | # httpx
20 | backports-tarfile==1.2.0
21 | # via
22 | # -c requirements.txt
23 | # jaraco-context
24 | build==1.2.1
25 | # via
26 | # -c requirements.txt
27 | # pip-tools
28 | certifi==2024.7.4
29 | # via
30 | # -c requirements.txt
31 | # httpcore
32 | # httpx
33 | click==8.1.7
34 | # via
35 | # -c requirements.txt
36 | # hatch.envs.test
37 | # hatch
38 | # pip-tools
39 | # userpath
40 | coverage==7.6.0
41 | # via pytest-cov
42 | distlib==0.3.8
43 | # via
44 | # -c requirements.txt
45 | # virtualenv
46 | execnet==2.1.1
47 | # via pytest-xdist
48 | filelock==3.15.4
49 | # via
50 | # -c requirements.txt
51 | # virtualenv
52 | h11==0.14.0
53 | # via
54 | # -c requirements.txt
55 | # httpcore
56 | hatch==1.12.0
57 | # via
58 | # -c requirements.txt
59 | # hatch.envs.test
60 | hatchling==1.25.0
61 | # via
62 | # -c requirements.txt
63 | # hatch
64 | httpcore==1.0.5
65 | # via
66 | # -c requirements.txt
67 | # httpx
68 | httpx==0.27.0
69 | # via
70 | # -c requirements.txt
71 | # hatch
72 | hyperlink==21.0.0
73 | # via
74 | # -c requirements.txt
75 | # hatch
76 | idna==3.7
77 | # via
78 | # -c requirements.txt
79 | # anyio
80 | # httpx
81 | # hyperlink
82 | importlib-metadata==8.0.0
83 | # via
84 | # -c requirements.txt
85 | # keyring
86 | iniconfig==2.0.0
87 | # via pytest
88 | jaraco-classes==3.4.0
89 | # via
90 | # -c requirements.txt
91 | # keyring
92 | jaraco-context==5.3.0
93 | # via
94 | # -c requirements.txt
95 | # keyring
96 | jaraco-functools==4.0.1
97 | # via
98 | # -c requirements.txt
99 | # keyring
100 | keyring==25.2.1
101 | # via
102 | # -c requirements.txt
103 | # hatch
104 | markdown-it-py==3.0.0
105 | # via
106 | # -c requirements.txt
107 | # rich
108 | mdurl==0.1.2
109 | # via
110 | # -c requirements.txt
111 | # markdown-it-py
112 | more-itertools==10.3.0
113 | # via
114 | # -c requirements.txt
115 | # jaraco-classes
116 | # jaraco-functools
117 | packaging==24.1
118 | # via
119 | # -c requirements.txt
120 | # build
121 | # hatch
122 | # hatchling
123 | # pytest
124 | pathspec==0.12.1
125 | # via
126 | # -c requirements.txt
127 | # hatchling
128 | pexpect==4.9.0
129 | # via
130 | # -c requirements.txt
131 | # hatch
132 | pip-tools==7.4.1
133 | # via
134 | # -c requirements.txt
135 | # hatch.envs.test
136 | platformdirs==4.2.2
137 | # via
138 | # -c requirements.txt
139 | # hatch
140 | # virtualenv
141 | pluggy==1.5.0
142 | # via
143 | # -c requirements.txt
144 | # hatchling
145 | # pytest
146 | ptyprocess==0.7.0
147 | # via
148 | # -c requirements.txt
149 | # pexpect
150 | pygments==2.18.0
151 | # via
152 | # -c requirements.txt
153 | # rich
154 | pyproject-hooks==1.1.0
155 | # via
156 | # -c requirements.txt
157 | # build
158 | # pip-tools
159 | pytest==8.2.2
160 | # via
161 | # hatch.envs.test
162 | # pytest-cov
163 | # pytest-xdist
164 | pytest-cov==5.0.0
165 | # via hatch.envs.test
166 | pytest-xdist==3.6.1
167 | # via hatch.envs.test
168 | rich==13.7.1
169 | # via
170 | # -c requirements.txt
171 | # hatch.envs.test
172 | # hatch
173 | shellingham==1.5.4
174 | # via
175 | # -c requirements.txt
176 | # hatch
177 | sniffio==1.3.1
178 | # via
179 | # -c requirements.txt
180 | # anyio
181 | # httpx
182 | tomli-w==1.0.0
183 | # via
184 | # -c requirements.txt
185 | # hatch
186 | tomlkit==0.13.0
187 | # via
188 | # -c requirements.txt
189 | # hatch.envs.test
190 | # hatch
191 | trove-classifiers==2024.7.2
192 | # via
193 | # -c requirements.txt
194 | # hatchling
195 | userpath==1.9.2
196 | # via
197 | # -c requirements.txt
198 | # hatch
199 | uv==0.2.24
200 | # via
201 | # -c requirements.txt
202 | # hatch
203 | virtualenv==20.26.3
204 | # via
205 | # -c requirements.txt
206 | # hatch
207 | wheel==0.43.0
208 | # via
209 | # -c requirements.txt
210 | # pip-tools
211 | zipp==3.19.2
212 | # via
213 | # -c requirements.txt
214 | # importlib-metadata
215 | zstandard==0.22.0
216 | # via
217 | # -c requirements.txt
218 | # hatch
219 |
220 | # The following packages are considered to be unsafe in a requirements file:
221 | # pip
222 | # setuptools
223 |
--------------------------------------------------------------------------------
/requirements/requirements-versions.1.10.x.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # - pytest
5 | # - pytest-cov
6 | # - tomlkit
7 | # - pytest-xdist
8 | # - hatch~=1.10.0
9 | # - click
10 | # - hatch<2,>=1.7.0
11 | # - pip-tools>=6
12 | # - rich
13 | #
14 |
15 | anyio==4.4.0
16 | # via httpx
17 | backports-tarfile==1.2.0
18 | # via jaraco-context
19 | build==1.2.1
20 | # via pip-tools
21 | certifi==2024.7.4
22 | # via
23 | # httpcore
24 | # httpx
25 | click==8.1.7
26 | # via
27 | # hatch.envs.versions.1.10.x
28 | # hatch
29 | # pip-tools
30 | # userpath
31 | coverage==7.6.0
32 | # via pytest-cov
33 | distlib==0.3.8
34 | # via virtualenv
35 | execnet==2.1.1
36 | # via pytest-xdist
37 | filelock==3.15.4
38 | # via virtualenv
39 | h11==0.14.0
40 | # via httpcore
41 | hatch==1.10.0
42 | # via hatch.envs.versions.1.10.x
43 | hatchling==1.25.0
44 | # via hatch
45 | httpcore==1.0.5
46 | # via httpx
47 | httpx==0.27.0
48 | # via hatch
49 | hyperlink==21.0.0
50 | # via hatch
51 | idna==3.7
52 | # via
53 | # anyio
54 | # httpx
55 | # hyperlink
56 | importlib-metadata==8.0.0
57 | # via keyring
58 | iniconfig==2.0.0
59 | # via pytest
60 | jaraco-classes==3.4.0
61 | # via keyring
62 | jaraco-context==5.3.0
63 | # via keyring
64 | jaraco-functools==4.0.1
65 | # via keyring
66 | keyring==25.2.1
67 | # via hatch
68 | markdown-it-py==3.0.0
69 | # via rich
70 | mdurl==0.1.2
71 | # via markdown-it-py
72 | more-itertools==10.3.0
73 | # via
74 | # jaraco-classes
75 | # jaraco-functools
76 | packaging==24.1
77 | # via
78 | # build
79 | # hatch
80 | # hatchling
81 | # pytest
82 | pathspec==0.12.1
83 | # via hatchling
84 | pexpect==4.9.0
85 | # via hatch
86 | pip-tools==7.4.1
87 | # via hatch.envs.versions.1.10.x
88 | platformdirs==4.2.2
89 | # via
90 | # hatch
91 | # virtualenv
92 | pluggy==1.5.0
93 | # via
94 | # hatchling
95 | # pytest
96 | ptyprocess==0.7.0
97 | # via pexpect
98 | pygments==2.18.0
99 | # via rich
100 | pyproject-hooks==1.1.0
101 | # via
102 | # build
103 | # pip-tools
104 | pytest==8.2.2
105 | # via
106 | # hatch.envs.versions.1.10.x
107 | # pytest-cov
108 | # pytest-xdist
109 | pytest-cov==5.0.0
110 | # via hatch.envs.versions.1.10.x
111 | pytest-xdist==3.6.1
112 | # via hatch.envs.versions.1.10.x
113 | rich==13.7.1
114 | # via
115 | # hatch.envs.versions.1.10.x
116 | # hatch
117 | shellingham==1.5.4
118 | # via hatch
119 | sniffio==1.3.1
120 | # via
121 | # anyio
122 | # httpx
123 | tomli-w==1.0.0
124 | # via hatch
125 | tomlkit==0.13.0
126 | # via
127 | # hatch.envs.versions.1.10.x
128 | # hatch
129 | trove-classifiers==2024.7.2
130 | # via hatchling
131 | userpath==1.9.2
132 | # via hatch
133 | uv==0.2.24
134 | # via hatch
135 | virtualenv==20.26.3
136 | # via hatch
137 | wheel==0.43.0
138 | # via pip-tools
139 | zipp==3.19.2
140 | # via importlib-metadata
141 | zstandard==0.22.0
142 | # via hatch
143 |
144 | # The following packages are considered to be unsafe in a requirements file:
145 | # pip
146 | # setuptools
147 |
--------------------------------------------------------------------------------
/requirements/requirements-versions.1.11.x.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # - pytest
5 | # - pytest-cov
6 | # - tomlkit
7 | # - pytest-xdist
8 | # - hatch~=1.11.1
9 | # - click
10 | # - hatch<2,>=1.7.0
11 | # - pip-tools>=6
12 | # - rich
13 | #
14 |
15 | anyio==4.4.0
16 | # via httpx
17 | backports-tarfile==1.2.0
18 | # via jaraco-context
19 | build==1.2.1
20 | # via pip-tools
21 | certifi==2024.7.4
22 | # via
23 | # httpcore
24 | # httpx
25 | click==8.1.7
26 | # via
27 | # hatch.envs.versions.1.11.x
28 | # hatch
29 | # pip-tools
30 | # userpath
31 | coverage==7.6.0
32 | # via pytest-cov
33 | distlib==0.3.8
34 | # via virtualenv
35 | execnet==2.1.1
36 | # via pytest-xdist
37 | filelock==3.15.4
38 | # via virtualenv
39 | h11==0.14.0
40 | # via httpcore
41 | hatch==1.11.1
42 | # via hatch.envs.versions.1.11.x
43 | hatchling==1.25.0
44 | # via hatch
45 | httpcore==1.0.5
46 | # via httpx
47 | httpx==0.27.0
48 | # via hatch
49 | hyperlink==21.0.0
50 | # via hatch
51 | idna==3.7
52 | # via
53 | # anyio
54 | # httpx
55 | # hyperlink
56 | importlib-metadata==8.0.0
57 | # via keyring
58 | iniconfig==2.0.0
59 | # via pytest
60 | jaraco-classes==3.4.0
61 | # via keyring
62 | jaraco-context==5.3.0
63 | # via keyring
64 | jaraco-functools==4.0.1
65 | # via keyring
66 | keyring==25.2.1
67 | # via hatch
68 | markdown-it-py==3.0.0
69 | # via rich
70 | mdurl==0.1.2
71 | # via markdown-it-py
72 | more-itertools==10.3.0
73 | # via
74 | # jaraco-classes
75 | # jaraco-functools
76 | packaging==24.1
77 | # via
78 | # build
79 | # hatch
80 | # hatchling
81 | # pytest
82 | pathspec==0.12.1
83 | # via hatchling
84 | pexpect==4.9.0
85 | # via hatch
86 | pip-tools==7.4.1
87 | # via hatch.envs.versions.1.11.x
88 | platformdirs==4.2.2
89 | # via
90 | # hatch
91 | # virtualenv
92 | pluggy==1.5.0
93 | # via
94 | # hatchling
95 | # pytest
96 | ptyprocess==0.7.0
97 | # via pexpect
98 | pygments==2.18.0
99 | # via rich
100 | pyproject-hooks==1.1.0
101 | # via
102 | # build
103 | # pip-tools
104 | pytest==8.2.2
105 | # via
106 | # hatch.envs.versions.1.11.x
107 | # pytest-cov
108 | # pytest-xdist
109 | pytest-cov==5.0.0
110 | # via hatch.envs.versions.1.11.x
111 | pytest-xdist==3.6.1
112 | # via hatch.envs.versions.1.11.x
113 | rich==13.7.1
114 | # via
115 | # hatch.envs.versions.1.11.x
116 | # hatch
117 | shellingham==1.5.4
118 | # via hatch
119 | sniffio==1.3.1
120 | # via
121 | # anyio
122 | # httpx
123 | tomli-w==1.0.0
124 | # via hatch
125 | tomlkit==0.13.0
126 | # via
127 | # hatch.envs.versions.1.11.x
128 | # hatch
129 | trove-classifiers==2024.7.2
130 | # via hatchling
131 | userpath==1.9.2
132 | # via hatch
133 | uv==0.2.24
134 | # via hatch
135 | virtualenv==20.26.3
136 | # via hatch
137 | wheel==0.43.0
138 | # via pip-tools
139 | zipp==3.19.2
140 | # via importlib-metadata
141 | zstandard==0.22.0
142 | # via hatch
143 |
144 | # The following packages are considered to be unsafe in a requirements file:
145 | # pip
146 | # setuptools
147 |
--------------------------------------------------------------------------------
/requirements/requirements-versions.1.12.x.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # - pytest
5 | # - pytest-cov
6 | # - tomlkit
7 | # - pytest-xdist
8 | # - hatch~=1.12.0
9 | # - click
10 | # - hatch<2,>=1.7.0
11 | # - pip-tools>=6
12 | # - rich
13 | #
14 |
15 | anyio==4.4.0
16 | # via httpx
17 | backports-tarfile==1.2.0
18 | # via jaraco-context
19 | build==1.2.1
20 | # via pip-tools
21 | certifi==2024.7.4
22 | # via
23 | # httpcore
24 | # httpx
25 | click==8.1.7
26 | # via
27 | # hatch.envs.versions.1.12.x
28 | # hatch
29 | # pip-tools
30 | # userpath
31 | coverage==7.6.0
32 | # via pytest-cov
33 | distlib==0.3.8
34 | # via virtualenv
35 | execnet==2.1.1
36 | # via pytest-xdist
37 | filelock==3.15.4
38 | # via virtualenv
39 | h11==0.14.0
40 | # via httpcore
41 | hatch==1.12.0
42 | # via hatch.envs.versions.1.12.x
43 | hatchling==1.25.0
44 | # via hatch
45 | httpcore==1.0.5
46 | # via httpx
47 | httpx==0.27.0
48 | # via hatch
49 | hyperlink==21.0.0
50 | # via hatch
51 | idna==3.7
52 | # via
53 | # anyio
54 | # httpx
55 | # hyperlink
56 | importlib-metadata==8.0.0
57 | # via keyring
58 | iniconfig==2.0.0
59 | # via pytest
60 | jaraco-classes==3.4.0
61 | # via keyring
62 | jaraco-context==5.3.0
63 | # via keyring
64 | jaraco-functools==4.0.1
65 | # via keyring
66 | keyring==25.2.1
67 | # via hatch
68 | markdown-it-py==3.0.0
69 | # via rich
70 | mdurl==0.1.2
71 | # via markdown-it-py
72 | more-itertools==10.3.0
73 | # via
74 | # jaraco-classes
75 | # jaraco-functools
76 | packaging==24.1
77 | # via
78 | # build
79 | # hatch
80 | # hatchling
81 | # pytest
82 | pathspec==0.12.1
83 | # via hatchling
84 | pexpect==4.9.0
85 | # via hatch
86 | pip-tools==7.4.1
87 | # via hatch.envs.versions.1.12.x
88 | platformdirs==4.2.2
89 | # via
90 | # hatch
91 | # virtualenv
92 | pluggy==1.5.0
93 | # via
94 | # hatchling
95 | # pytest
96 | ptyprocess==0.7.0
97 | # via pexpect
98 | pygments==2.18.0
99 | # via rich
100 | pyproject-hooks==1.1.0
101 | # via
102 | # build
103 | # pip-tools
104 | pytest==8.2.2
105 | # via
106 | # hatch.envs.versions.1.12.x
107 | # pytest-cov
108 | # pytest-xdist
109 | pytest-cov==5.0.0
110 | # via hatch.envs.versions.1.12.x
111 | pytest-xdist==3.6.1
112 | # via hatch.envs.versions.1.12.x
113 | rich==13.7.1
114 | # via
115 | # hatch.envs.versions.1.12.x
116 | # hatch
117 | shellingham==1.5.4
118 | # via hatch
119 | sniffio==1.3.1
120 | # via
121 | # anyio
122 | # httpx
123 | tomli-w==1.0.0
124 | # via hatch
125 | tomlkit==0.13.0
126 | # via
127 | # hatch.envs.versions.1.12.x
128 | # hatch
129 | trove-classifiers==2024.7.2
130 | # via hatchling
131 | userpath==1.9.2
132 | # via hatch
133 | uv==0.2.24
134 | # via hatch
135 | virtualenv==20.26.3
136 | # via hatch
137 | wheel==0.43.0
138 | # via pip-tools
139 | zipp==3.19.2
140 | # via importlib-metadata
141 | zstandard==0.22.0
142 | # via hatch
143 |
144 | # The following packages are considered to be unsafe in a requirements file:
145 | # pip
146 | # setuptools
147 |
--------------------------------------------------------------------------------
/requirements/requirements-versions.1.7.x.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # - pytest
5 | # - pytest-cov
6 | # - tomlkit
7 | # - pytest-xdist
8 | # - hatch~=1.7.0
9 | # - click
10 | # - hatch<2,>=1.7.0
11 | # - pip-tools>=6
12 | # - rich
13 | #
14 |
15 | anyio==4.4.0
16 | # via httpx
17 | backports-tarfile==1.2.0
18 | # via jaraco-context
19 | build==1.2.1
20 | # via pip-tools
21 | certifi==2024.7.4
22 | # via
23 | # httpcore
24 | # httpx
25 | click==8.1.7
26 | # via
27 | # hatch.envs.versions.1.7.x
28 | # hatch
29 | # pip-tools
30 | # userpath
31 | coverage==7.6.0
32 | # via pytest-cov
33 | distlib==0.3.8
34 | # via virtualenv
35 | execnet==2.1.1
36 | # via pytest-xdist
37 | filelock==3.15.4
38 | # via virtualenv
39 | h11==0.14.0
40 | # via httpcore
41 | hatch==1.7.0
42 | # via hatch.envs.versions.1.7.x
43 | hatchling==1.25.0
44 | # via hatch
45 | httpcore==1.0.5
46 | # via httpx
47 | httpx==0.27.0
48 | # via hatch
49 | hyperlink==21.0.0
50 | # via hatch
51 | idna==3.7
52 | # via
53 | # anyio
54 | # httpx
55 | # hyperlink
56 | importlib-metadata==8.0.0
57 | # via keyring
58 | iniconfig==2.0.0
59 | # via pytest
60 | jaraco-classes==3.4.0
61 | # via keyring
62 | jaraco-context==5.3.0
63 | # via keyring
64 | jaraco-functools==4.0.1
65 | # via keyring
66 | keyring==25.2.1
67 | # via hatch
68 | markdown-it-py==3.0.0
69 | # via rich
70 | mdurl==0.1.2
71 | # via markdown-it-py
72 | more-itertools==10.3.0
73 | # via
74 | # jaraco-classes
75 | # jaraco-functools
76 | packaging==24.1
77 | # via
78 | # build
79 | # hatch
80 | # hatchling
81 | # pytest
82 | pathspec==0.12.1
83 | # via hatchling
84 | pexpect==4.9.0
85 | # via hatch
86 | pip-tools==7.4.1
87 | # via hatch.envs.versions.1.7.x
88 | platformdirs==4.2.2
89 | # via
90 | # hatch
91 | # virtualenv
92 | pluggy==1.5.0
93 | # via
94 | # hatchling
95 | # pytest
96 | ptyprocess==0.7.0
97 | # via pexpect
98 | pygments==2.18.0
99 | # via rich
100 | pyperclip==1.9.0
101 | # via hatch
102 | pyproject-hooks==1.1.0
103 | # via
104 | # build
105 | # pip-tools
106 | pytest==8.2.2
107 | # via
108 | # hatch.envs.versions.1.7.x
109 | # pytest-cov
110 | # pytest-xdist
111 | pytest-cov==5.0.0
112 | # via hatch.envs.versions.1.7.x
113 | pytest-xdist==3.6.1
114 | # via hatch.envs.versions.1.7.x
115 | rich==13.7.1
116 | # via
117 | # hatch.envs.versions.1.7.x
118 | # hatch
119 | shellingham==1.5.4
120 | # via hatch
121 | sniffio==1.3.1
122 | # via
123 | # anyio
124 | # httpx
125 | tomli-w==1.0.0
126 | # via hatch
127 | tomlkit==0.13.0
128 | # via
129 | # hatch.envs.versions.1.7.x
130 | # hatch
131 | trove-classifiers==2024.7.2
132 | # via hatchling
133 | userpath==1.9.2
134 | # via hatch
135 | virtualenv==20.26.3
136 | # via hatch
137 | wheel==0.43.0
138 | # via pip-tools
139 | zipp==3.19.2
140 | # via importlib-metadata
141 |
142 | # The following packages are considered to be unsafe in a requirements file:
143 | # pip
144 | # setuptools
145 |
--------------------------------------------------------------------------------
/requirements/requirements-versions.1.8.x.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # - pytest
5 | # - pytest-cov
6 | # - tomlkit
7 | # - pytest-xdist
8 | # - hatch~=1.8.1
9 | # - click
10 | # - hatch<2,>=1.7.0
11 | # - pip-tools>=6
12 | # - rich
13 | #
14 |
15 | anyio==4.4.0
16 | # via httpx
17 | backports-tarfile==1.2.0
18 | # via jaraco-context
19 | build==1.2.1
20 | # via pip-tools
21 | certifi==2024.7.4
22 | # via
23 | # httpcore
24 | # httpx
25 | click==8.1.7
26 | # via
27 | # hatch.envs.versions.1.8.x
28 | # hatch
29 | # pip-tools
30 | # userpath
31 | coverage==7.6.0
32 | # via pytest-cov
33 | distlib==0.3.8
34 | # via virtualenv
35 | execnet==2.1.1
36 | # via pytest-xdist
37 | filelock==3.15.4
38 | # via virtualenv
39 | h11==0.14.0
40 | # via httpcore
41 | hatch==1.8.1
42 | # via hatch.envs.versions.1.8.x
43 | hatchling==1.25.0
44 | # via hatch
45 | httpcore==1.0.5
46 | # via httpx
47 | httpx==0.27.0
48 | # via hatch
49 | hyperlink==21.0.0
50 | # via hatch
51 | idna==3.7
52 | # via
53 | # anyio
54 | # httpx
55 | # hyperlink
56 | importlib-metadata==8.0.0
57 | # via keyring
58 | iniconfig==2.0.0
59 | # via pytest
60 | jaraco-classes==3.4.0
61 | # via keyring
62 | jaraco-context==5.3.0
63 | # via keyring
64 | jaraco-functools==4.0.1
65 | # via keyring
66 | keyring==25.2.1
67 | # via hatch
68 | markdown-it-py==3.0.0
69 | # via rich
70 | mdurl==0.1.2
71 | # via markdown-it-py
72 | more-itertools==10.3.0
73 | # via
74 | # jaraco-classes
75 | # jaraco-functools
76 | packaging==24.1
77 | # via
78 | # build
79 | # hatch
80 | # hatchling
81 | # pytest
82 | pathspec==0.12.1
83 | # via hatchling
84 | pexpect==4.9.0
85 | # via hatch
86 | pip-tools==7.4.1
87 | # via hatch.envs.versions.1.8.x
88 | platformdirs==4.2.2
89 | # via
90 | # hatch
91 | # virtualenv
92 | pluggy==1.5.0
93 | # via
94 | # hatchling
95 | # pytest
96 | ptyprocess==0.7.0
97 | # via pexpect
98 | pygments==2.18.0
99 | # via rich
100 | pyproject-hooks==1.1.0
101 | # via
102 | # build
103 | # pip-tools
104 | pytest==8.2.2
105 | # via
106 | # hatch.envs.versions.1.8.x
107 | # pytest-cov
108 | # pytest-xdist
109 | pytest-cov==5.0.0
110 | # via hatch.envs.versions.1.8.x
111 | pytest-xdist==3.6.1
112 | # via hatch.envs.versions.1.8.x
113 | rich==13.7.1
114 | # via
115 | # hatch.envs.versions.1.8.x
116 | # hatch
117 | shellingham==1.5.4
118 | # via hatch
119 | sniffio==1.3.1
120 | # via
121 | # anyio
122 | # httpx
123 | tomli-w==1.0.0
124 | # via hatch
125 | tomlkit==0.13.0
126 | # via
127 | # hatch.envs.versions.1.8.x
128 | # hatch
129 | trove-classifiers==2024.7.2
130 | # via hatchling
131 | userpath==1.9.2
132 | # via hatch
133 | virtualenv==20.26.3
134 | # via hatch
135 | wheel==0.43.0
136 | # via pip-tools
137 | zipp==3.19.2
138 | # via importlib-metadata
139 | zstandard==0.22.0
140 | # via hatch
141 |
142 | # The following packages are considered to be unsafe in a requirements file:
143 | # pip
144 | # setuptools
145 |
--------------------------------------------------------------------------------
/requirements/requirements-versions.1.9.x.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # - pytest
5 | # - pytest-cov
6 | # - tomlkit
7 | # - pytest-xdist
8 | # - hatch~=1.9.7
9 | # - click
10 | # - hatch<2,>=1.7.0
11 | # - pip-tools>=6
12 | # - rich
13 | #
14 |
15 | anyio==4.4.0
16 | # via httpx
17 | backports-tarfile==1.2.0
18 | # via jaraco-context
19 | build==1.2.1
20 | # via pip-tools
21 | certifi==2024.7.4
22 | # via
23 | # httpcore
24 | # httpx
25 | click==8.1.7
26 | # via
27 | # hatch.envs.versions.1.9.x
28 | # hatch
29 | # pip-tools
30 | # userpath
31 | coverage==7.6.0
32 | # via pytest-cov
33 | distlib==0.3.8
34 | # via virtualenv
35 | editables==0.5
36 | # via hatchling
37 | execnet==2.1.1
38 | # via pytest-xdist
39 | filelock==3.15.4
40 | # via virtualenv
41 | h11==0.14.0
42 | # via httpcore
43 | hatch==1.9.7
44 | # via hatch.envs.versions.1.9.x
45 | hatchling==1.21.1
46 | # via hatch
47 | httpcore==1.0.5
48 | # via httpx
49 | httpx==0.27.0
50 | # via hatch
51 | hyperlink==21.0.0
52 | # via hatch
53 | idna==3.7
54 | # via
55 | # anyio
56 | # httpx
57 | # hyperlink
58 | importlib-metadata==8.0.0
59 | # via keyring
60 | iniconfig==2.0.0
61 | # via pytest
62 | jaraco-classes==3.4.0
63 | # via keyring
64 | jaraco-context==5.3.0
65 | # via keyring
66 | jaraco-functools==4.0.1
67 | # via keyring
68 | keyring==25.2.1
69 | # via hatch
70 | markdown-it-py==3.0.0
71 | # via rich
72 | mdurl==0.1.2
73 | # via markdown-it-py
74 | more-itertools==10.3.0
75 | # via
76 | # jaraco-classes
77 | # jaraco-functools
78 | packaging==24.1
79 | # via
80 | # build
81 | # hatch
82 | # hatchling
83 | # pytest
84 | pathspec==0.12.1
85 | # via hatchling
86 | pexpect==4.9.0
87 | # via hatch
88 | pip-tools==7.4.1
89 | # via hatch.envs.versions.1.9.x
90 | platformdirs==4.2.2
91 | # via
92 | # hatch
93 | # virtualenv
94 | pluggy==1.5.0
95 | # via
96 | # hatchling
97 | # pytest
98 | ptyprocess==0.7.0
99 | # via pexpect
100 | pygments==2.18.0
101 | # via rich
102 | pyproject-hooks==1.1.0
103 | # via
104 | # build
105 | # pip-tools
106 | pytest==8.2.2
107 | # via
108 | # hatch.envs.versions.1.9.x
109 | # pytest-cov
110 | # pytest-xdist
111 | pytest-cov==5.0.0
112 | # via hatch.envs.versions.1.9.x
113 | pytest-xdist==3.6.1
114 | # via hatch.envs.versions.1.9.x
115 | rich==13.7.1
116 | # via
117 | # hatch.envs.versions.1.9.x
118 | # hatch
119 | shellingham==1.5.4
120 | # via hatch
121 | sniffio==1.3.1
122 | # via
123 | # anyio
124 | # httpx
125 | tomli-w==1.0.0
126 | # via hatch
127 | tomlkit==0.13.0
128 | # via
129 | # hatch.envs.versions.1.9.x
130 | # hatch
131 | trove-classifiers==2024.7.2
132 | # via hatchling
133 | userpath==1.9.2
134 | # via hatch
135 | virtualenv==20.25.3
136 | # via hatch
137 | wheel==0.43.0
138 | # via pip-tools
139 | zipp==3.19.2
140 | # via importlib-metadata
141 | zstandard==0.22.0
142 | # via hatch
143 |
144 | # The following packages are considered to be unsafe in a requirements file:
145 | # pip
146 | # setuptools
147 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/juftin/hatch-pip-compile/9337724557a2a8efe663d76a98faf96d3176d063/tests/__init__.py
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | """
2 | Shared fixtures for tests.
3 | """
4 |
5 | from __future__ import annotations
6 |
7 | import contextlib
8 | import os
9 | import pathlib
10 | import shutil
11 | from dataclasses import dataclass, field
12 | from subprocess import CompletedProcess
13 | from typing import Generator
14 | from unittest.mock import patch
15 |
16 | import hatch
17 | import pytest
18 | import tomlkit
19 | from click.testing import CliRunner, Result
20 | from hatch.cli.application import Application
21 | from hatch.config.constants import AppEnvVars, ConfigEnvVars, PublishEnvVars
22 | from hatch.project.core import Project
23 | from hatch.utils.fs import Path, temp_directory
24 | from hatch.utils.platform import Platform
25 |
26 | from hatch_pip_compile.plugin import PipCompileEnvironment
27 |
28 |
29 | @pytest.fixture
30 | def mock_check_command() -> Generator[patch, None, None]:
31 | """
32 | Disable the `plugin_check_command` for testing
33 | """
34 | with patch("hatch_pip_compile.plugin.PipCompileEnvironment.plugin_check_command") as mock:
35 | mock.return_value = CompletedProcess(args=[], returncode=0, stdout=b"", stderr=b"")
36 | yield mock
37 |
38 |
39 | @pytest.fixture
40 | def subprocess_run() -> Generator[patch, None, None]:
41 | """
42 | Disable the `subprocess.run` for testing
43 | """
44 | with patch("subprocess.run") as mock:
45 | mock.return_value = CompletedProcess(args=[], returncode=0, stdout=b"", stderr=b"")
46 | yield mock
47 |
48 |
49 | @pytest.fixture
50 | def platform() -> Platform:
51 | """
52 | Platform
53 | """
54 | return Platform()
55 |
56 |
57 | @pytest.fixture
58 | def isolation(platform: Platform) -> Generator[Path, None, None]:
59 | """
60 | Isolated hatch environment for testing.
61 | """
62 | with temp_directory() as temp_dir:
63 | data_dir = pathlib.Path(__file__).parent / "data"
64 | shutil.copytree(data_dir, temp_dir, dirs_exist_ok=True)
65 | data_dir = temp_dir / "data"
66 | data_dir.mkdir()
67 | cache_dir = temp_dir / "cache"
68 | cache_dir.mkdir()
69 | default_env_vars = {
70 | AppEnvVars.NO_COLOR: "1",
71 | ConfigEnvVars.DATA: str(data_dir),
72 | ConfigEnvVars.CACHE: str(cache_dir),
73 | PublishEnvVars.REPO: "dev",
74 | "HATCH_SELF_TESTING": "true",
75 | "PYAPP_COMMAND_NAME": os.urandom(4).hex(),
76 | "GIT_AUTHOR_NAME": "Foo Bar",
77 | "GIT_AUTHOR_EMAIL": "foo@bar.baz",
78 | "COLUMNS": "80",
79 | "LINES": "24",
80 | }
81 | if platform.windows: # pragma: no cover
82 | default_env_vars["COMSPEC"] = "cmd.exe"
83 | else:
84 | default_env_vars["SHELL"] = "sh"
85 |
86 | with temp_dir.as_cwd(default_env_vars):
87 | os.environ.pop(AppEnvVars.ENV_ACTIVE, None)
88 | os.environ.pop(AppEnvVars.FORCE_COLOR, None)
89 | yield temp_dir
90 |
91 |
92 | @dataclass
93 | class PipCompileFixture:
94 | """
95 | Testing Fixture Data Container
96 | """
97 |
98 | __test__ = False
99 |
100 | isolation: pathlib.Path
101 | toml_doc: tomlkit.TOMLDocument
102 | pyproject: pathlib.Path
103 | project: Project
104 | platform: Platform
105 | isolated_data_dir: pathlib.Path
106 |
107 | application: Application = field(init=False)
108 | default_environment: PipCompileEnvironment = field(init=False)
109 | test_environment: PipCompileEnvironment = field(init=False)
110 | cli_runner: CliRunner = field(init=False)
111 |
112 | def __post_init__(self) -> None:
113 | """
114 | Post Init
115 | """
116 | self.application = Application(
117 | exit_func=lambda x: None, # noqa: ARG005
118 | verbosity=0,
119 | interactive=False,
120 | enable_color=False,
121 | )
122 | self.application.data_dir = self.isolated_data_dir / "data"
123 | self.application.config_file.load()
124 | self.application.cache_dir = self.isolated_data_dir / "cache"
125 | self.application.project = self.project
126 | self.current_environment = self.reload_environment("default")
127 | self.default_environment = self.reload_environment("default")
128 | self.test_environment = self.reload_environment("test")
129 | self.cli_runner = CliRunner()
130 |
131 | def reload_environment(self, environment: str | PipCompileEnvironment) -> PipCompileEnvironment:
132 | """
133 | Reload a new environment given the current state of the isolated project
134 | """
135 | if isinstance(environment, PipCompileEnvironment):
136 | environment_name = environment.name
137 | else:
138 | environment_name = environment
139 | env = self.application.get_environment(env_name=environment_name)
140 | return env
141 |
142 | def update_pyproject(self) -> None:
143 | """
144 | Update pyproject.toml
145 | """
146 | tomlkit.dump(self.toml_doc, self.pyproject.open("w"))
147 |
148 | @contextlib.contextmanager
149 | def chdir(self) -> Generator[None, None, None]:
150 | """
151 | Change the working directory to the isolation
152 | """
153 | current_dir = os.getcwd()
154 | try:
155 | os.chdir(self.isolation)
156 | yield
157 | finally:
158 | os.chdir(current_dir)
159 |
160 | def update_environment_resolver(
161 | self, environment: str | PipCompileEnvironment, resolver: str
162 | ) -> PipCompileEnvironment:
163 | """
164 | Update the environment resolver
165 | """
166 | if isinstance(environment, PipCompileEnvironment):
167 | environment_name = environment.name
168 | else:
169 | environment_name = environment
170 | self.toml_doc["tool"]["hatch"]["envs"][environment_name]["pip-compile-resolver"] = resolver
171 | self.update_pyproject()
172 | return self.reload_environment(environment_name)
173 |
174 | def update_environment_installer(
175 | self, environment: str | PipCompileEnvironment, installer: str
176 | ) -> PipCompileEnvironment:
177 | """
178 | Update the environment installer
179 | """
180 | if isinstance(environment, PipCompileEnvironment):
181 | environment_name = environment.name
182 | else:
183 | environment_name = environment
184 | self.toml_doc["tool"]["hatch"]["envs"][environment_name][
185 | "pip-compile-installer"
186 | ] = installer
187 | self.update_pyproject()
188 | return self.reload_environment(environment_name)
189 |
190 | def cli_invoke(self, args: list[str], env: dict[str, str] | None = None) -> Result:
191 | """
192 | Invoke the CLI
193 | """
194 | invoke_kwargs = {"args": args}
195 | if env:
196 | invoke_kwargs["env"] = env
197 | with self.cli_runner.isolated_filesystem(self.isolation):
198 | return self.cli_runner.invoke(hatch.cli.hatch, **invoke_kwargs)
199 |
200 | def invoke_environment(
201 | self, environment: PipCompileEnvironment, env: dict[str, str] | None = None
202 | ) -> Result:
203 | """
204 | Sync the environment
205 | """
206 | result = self.cli_invoke(
207 | args=["env", "run", "--env", environment.name, "--", "python", "--version"],
208 | env=env,
209 | )
210 | return result
211 |
212 | @staticmethod
213 | def virtualenv_exists(environment: PipCompileEnvironment) -> bool:
214 | """
215 | Check if the virtual environment exists
216 | """
217 | virtualenv_cfg = environment.virtual_env.directory / "pyvenv.cfg"
218 | return virtualenv_cfg.exists()
219 |
220 | def is_installed(
221 | self,
222 | environment: PipCompileEnvironment,
223 | package: str,
224 | ) -> bool:
225 | """
226 | Check if a package is installed in the environment
227 |
228 | This method simply checks if the package is in the site-packages directory
229 | of the virtual environment.
230 | """
231 | if not self.virtualenv_exists(environment=environment):
232 | return False
233 | if self.platform.windows:
234 | site_packages = environment.virtual_env.directory / "Lib" / "site-packages"
235 | if not site_packages.exists():
236 | return False
237 | else:
238 | site_packages_search = environment.virtual_env.directory.glob(
239 | "lib/python*/site-packages"
240 | )
241 | site_packages = next(site_packages_search, None)
242 | if site_packages is None:
243 | return False
244 | package_dir = site_packages / package
245 | return (package_dir / "__init__.py").exists()
246 |
247 |
248 | @pytest.fixture
249 | def pip_compile(
250 | isolation: Path,
251 | platform: Platform,
252 | ) -> PipCompileFixture:
253 | """
254 | PipCompile testing fixture
255 | """
256 | pyproject = isolation / "pyproject.toml"
257 | isolated_data_dir = Path(os.environ[ConfigEnvVars.DATA])
258 | return PipCompileFixture(
259 | isolation=isolation,
260 | toml_doc=tomlkit.parse(string=pyproject.read_text()),
261 | pyproject=pyproject,
262 | project=Project(path=isolation),
263 | platform=platform,
264 | isolated_data_dir=isolated_data_dir,
265 | )
266 |
267 |
268 | @pytest.fixture(autouse=True)
269 | def pip_compile_disable(monkeypatch: pytest.MonkeyPatch) -> None:
270 | """
271 | Delete the PIP_COMPILE_DISABLE environment variable
272 | """
273 | monkeypatch.delenv("PIP_COMPILE_DISABLE", raising=False)
274 |
275 |
276 | resolver_param = pytest.mark.parametrize("resolver", ["pip-compile", "uv"])
277 | installer_param = pytest.mark.parametrize("installer", ["pip", "pip-sync", "uv"])
278 |
--------------------------------------------------------------------------------
/tests/data/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/juftin/hatch-pip-compile/9337724557a2a8efe663d76a98faf96d3176d063/tests/data/README.md
--------------------------------------------------------------------------------
/tests/data/hatch_pip_compile_test.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/juftin/hatch-pip-compile/9337724557a2a8efe663d76a98faf96d3176d063/tests/data/hatch_pip_compile_test.py
--------------------------------------------------------------------------------
/tests/data/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | build-backend = "hatchling.build"
3 | requires = ["hatchling"]
4 |
5 | [project]
6 | authors = [
7 | {name = "Justin Flannery", email = "juftin@juftin.com"}
8 | ]
9 | dependencies = [
10 | "hatch"
11 | ]
12 | description = "testing hatch-pip-compile"
13 | license = "MIT"
14 | name = "hatch-pip-compile-test"
15 | readme = "README.md"
16 | requires-python = ">=3.8"
17 | version = "0.1.0"
18 |
19 | [tool.hatch.envs.default]
20 | path = ".venv/hatch-pip-compile-test"
21 | pip-compile-constraint = "default"
22 | type = "pip-compile"
23 |
24 | [tool.hatch.envs.docs]
25 | dependencies = [
26 | "mkdocs"
27 | ]
28 | dev-mode = false
29 | lock-filename = "requirements/{env_name}.lock"
30 | path = ".venv/docs"
31 | pip-compile-constraint = "misc"
32 | pip-compile-hashes = true
33 |
34 | [tool.hatch.envs.lint]
35 | dependencies = [
36 | "mypy>=1.6.1",
37 | "ruff~=0.1.4"
38 | ]
39 | detached = true
40 | path = ".venv/lint"
41 | type = "pip-compile"
42 |
43 | [tool.hatch.envs.misc]
44 | dependencies = []
45 | detached = true
46 | path = ".venv/misc"
47 | skip-install = true
48 | type = "pip-compile"
49 |
50 | [tool.hatch.envs.test]
51 | dependencies = [
52 | "pytest",
53 | "pytest-cov"
54 | ]
55 | path = ".venv/test"
56 |
--------------------------------------------------------------------------------
/tests/data/requirements.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # - hatch
5 | #
6 |
7 | anyio==4.1.0
8 | # via httpx
9 | certifi==2023.11.17
10 | # via
11 | # httpcore
12 | # httpx
13 | cffi==1.16.0
14 | # via cryptography
15 | click==8.1.7
16 | # via
17 | # hatch
18 | # userpath
19 | cryptography==41.0.7
20 | # via secretstorage
21 | distlib==0.3.7
22 | # via virtualenv
23 | editables==0.5
24 | # via hatchling
25 | filelock==3.13.1
26 | # via virtualenv
27 | h11==0.14.0
28 | # via httpcore
29 | hatch==1.7.0
30 | # via hatch.envs.default
31 | hatchling==1.18.0
32 | # via hatch
33 | httpcore==1.0.2
34 | # via httpx
35 | httpx==0.25.2
36 | # via hatch
37 | hyperlink==21.0.0
38 | # via hatch
39 | idna==3.6
40 | # via
41 | # anyio
42 | # httpx
43 | # hyperlink
44 | importlib-metadata==7.0.0
45 | # via keyring
46 | jaraco-classes==3.3.0
47 | # via keyring
48 | jeepney==0.8.0
49 | # via
50 | # keyring
51 | # secretstorage
52 | keyring==24.3.0
53 | # via hatch
54 | markdown-it-py==3.0.0
55 | # via rich
56 | mdurl==0.1.2
57 | # via markdown-it-py
58 | more-itertools==10.1.0
59 | # via jaraco-classes
60 | packaging==23.2
61 | # via
62 | # hatch
63 | # hatchling
64 | pathspec==0.11.2
65 | # via hatchling
66 | pexpect==4.9.0
67 | # via hatch
68 | platformdirs==4.1.0
69 | # via
70 | # hatch
71 | # virtualenv
72 | pluggy==1.3.0
73 | # via hatchling
74 | ptyprocess==0.7.0
75 | # via pexpect
76 | pycparser==2.21
77 | # via cffi
78 | pygments==2.17.2
79 | # via rich
80 | pyperclip==1.8.2
81 | # via hatch
82 | rich==13.7.0
83 | # via hatch
84 | secretstorage==3.3.3
85 | # via keyring
86 | shellingham==1.5.4
87 | # via hatch
88 | sniffio==1.3.0
89 | # via
90 | # anyio
91 | # httpx
92 | tomli-w==1.0.0
93 | # via hatch
94 | tomlkit==0.12.5
95 | # via hatch
96 | trove-classifiers==2023.11.29
97 | # via hatchling
98 | userpath==1.9.1
99 | # via hatch
100 | virtualenv==20.25.0
101 | # via hatch
102 | zipp==3.17.0
103 | # via importlib-metadata
104 |
--------------------------------------------------------------------------------
/tests/data/requirements/requirements-lint.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # - mypy>=1.6.1
5 | # - ruff~=0.1.4
6 | #
7 |
8 | mypy==1.7.1
9 | # via hatch.envs.lint
10 | mypy-extensions==1.0.0
11 | # via mypy
12 | ruff==0.1.6
13 | # via hatch.envs.lint
14 | typing-extensions==4.8.0
15 | # via mypy
16 |
--------------------------------------------------------------------------------
/tests/data/requirements/requirements-test.txt:
--------------------------------------------------------------------------------
1 | #
2 | # This file is autogenerated by hatch-pip-compile with Python 3.11
3 | #
4 | # [constraints] requirements.txt (SHA256: 9dc610f2c50b92a04dc522873ebc8dd69d35bf8ce9feeef14c5341e8e4ef3019)
5 | #
6 | # - pytest
7 | # - pytest-cov
8 | # - hatch
9 | #
10 |
11 | anyio==4.1.0
12 | # via
13 | # -c requirements.txt
14 | # httpx
15 | certifi==2023.11.17
16 | # via
17 | # -c requirements.txt
18 | # httpcore
19 | # httpx
20 | cffi==1.16.0
21 | # via
22 | # -c requirements.txt
23 | # cryptography
24 | click==8.1.7
25 | # via
26 | # -c requirements.txt
27 | # hatch
28 | # userpath
29 | coverage==7.3.2
30 | # via
31 | # coverage
32 | # pytest-cov
33 | cryptography==41.0.7
34 | # via
35 | # -c requirements.txt
36 | # secretstorage
37 | distlib==0.3.7
38 | # via
39 | # -c requirements.txt
40 | # virtualenv
41 | editables==0.5
42 | # via
43 | # -c requirements.txt
44 | # hatchling
45 | filelock==3.13.1
46 | # via
47 | # -c requirements.txt
48 | # virtualenv
49 | h11==0.14.0
50 | # via
51 | # -c requirements.txt
52 | # httpcore
53 | hatch==1.7.0
54 | # via
55 | # -c requirements.txt
56 | # hatch.envs.test
57 | hatchling==1.18.0
58 | # via
59 | # -c requirements.txt
60 | # hatch
61 | httpcore==1.0.2
62 | # via
63 | # -c requirements.txt
64 | # httpx
65 | httpx==0.25.2
66 | # via
67 | # -c requirements.txt
68 | # hatch
69 | hyperlink==21.0.0
70 | # via
71 | # -c requirements.txt
72 | # hatch
73 | idna==3.6
74 | # via
75 | # -c requirements.txt
76 | # anyio
77 | # httpx
78 | # hyperlink
79 | importlib-metadata==7.0.0
80 | # via
81 | # -c requirements.txt
82 | # keyring
83 | iniconfig==2.0.0
84 | # via pytest
85 | jaraco-classes==3.3.0
86 | # via
87 | # -c requirements.txt
88 | # keyring
89 | jeepney==0.8.0
90 | # via
91 | # -c requirements.txt
92 | # keyring
93 | # secretstorage
94 | keyring==24.3.0
95 | # via
96 | # -c requirements.txt
97 | # hatch
98 | markdown-it-py==3.0.0
99 | # via
100 | # -c requirements.txt
101 | # rich
102 | mdurl==0.1.2
103 | # via
104 | # -c requirements.txt
105 | # markdown-it-py
106 | more-itertools==10.1.0
107 | # via
108 | # -c requirements.txt
109 | # jaraco-classes
110 | packaging==23.2
111 | # via
112 | # -c requirements.txt
113 | # hatch
114 | # hatchling
115 | # pytest
116 | pathspec==0.11.2
117 | # via
118 | # -c requirements.txt
119 | # hatchling
120 | pexpect==4.9.0
121 | # via
122 | # -c requirements.txt
123 | # hatch
124 | platformdirs==4.1.0
125 | # via
126 | # -c requirements.txt
127 | # hatch
128 | # virtualenv
129 | pluggy==1.3.0
130 | # via
131 | # -c requirements.txt
132 | # hatchling
133 | # pytest
134 | ptyprocess==0.7.0
135 | # via
136 | # -c requirements.txt
137 | # pexpect
138 | pycparser==2.21
139 | # via
140 | # -c requirements.txt
141 | # cffi
142 | pygments==2.17.2
143 | # via
144 | # -c requirements.txt
145 | # rich
146 | pyperclip==1.8.2
147 | # via
148 | # -c requirements.txt
149 | # hatch
150 | pytest==7.4.3
151 | # via
152 | # hatch.envs.test
153 | # pytest-cov
154 | pytest-cov==4.1.0
155 | # via hatch.envs.test
156 | rich==13.7.0
157 | # via
158 | # -c requirements.txt
159 | # hatch
160 | secretstorage==3.3.3
161 | # via
162 | # -c requirements.txt
163 | # keyring
164 | shellingham==1.5.4
165 | # via
166 | # -c requirements.txt
167 | # hatch
168 | sniffio==1.3.0
169 | # via
170 | # -c requirements.txt
171 | # anyio
172 | # httpx
173 | tomli-w==1.0.0
174 | # via
175 | # -c requirements.txt
176 | # hatch
177 | tomlkit==0.12.5
178 | # via
179 | # -c requirements.txt
180 | # hatch
181 | trove-classifiers==2023.11.29
182 | # via
183 | # -c requirements.txt
184 | # hatchling
185 | userpath==1.9.1
186 | # via
187 | # -c requirements.txt
188 | # hatch
189 | virtualenv==20.25.0
190 | # via
191 | # -c requirements.txt
192 | # hatch
193 | zipp==3.17.0
194 | # via
195 | # -c requirements.txt
196 | # importlib-metadata
197 |
--------------------------------------------------------------------------------
/tests/test_cli.py:
--------------------------------------------------------------------------------
1 | """
2 | Testing the hatch-pip-compile CLI
3 | """
4 |
5 | from unittest.mock import Mock
6 |
7 | import click
8 | import pytest
9 | from click.testing import CliRunner
10 |
11 | from hatch_pip_compile import __version__
12 | from hatch_pip_compile.cli import HatchCommandRunner, cli
13 | from tests.conftest import PipCompileFixture
14 |
15 |
16 | def test_cli_help() -> None:
17 | """
18 | Test the CLI with the --help flag
19 | """
20 | runner = CliRunner()
21 | result = runner.invoke(cli=cli, args=["--help"])
22 | assert result.exit_code == 0
23 |
24 |
25 | def test_cli_version() -> None:
26 | """
27 | Test the CLI with the --version flag
28 | """
29 | runner = CliRunner()
30 | result = runner.invoke(cli=cli, args=["--version"])
31 | assert result.exit_code == 0
32 | assert f"hatch-pip-compile, version {__version__}" in result.output
33 |
34 |
35 | def test_cli_no_args_mocked(pip_compile: PipCompileFixture, subprocess_run: Mock) -> None:
36 | """
37 | Test the CLI with no arguments - mock the result
38 | """
39 | runner = CliRunner()
40 | with runner.isolated_filesystem(temp_dir=pip_compile.isolation):
41 | _ = runner.invoke(cli=cli)
42 | assert subprocess_run.call_count == 1
43 | subprocess_run.assert_called_once()
44 | subprocess_run.assert_called_with(
45 | args=["hatch", "env", "show", "--json"], capture_output=True, check=True
46 | )
47 |
48 |
49 | def test_cli_no_args(pip_compile: PipCompileFixture) -> None:
50 | """
51 | Test the full CLI with no arguments
52 | """
53 | runner = CliRunner()
54 | with runner.isolated_filesystem(temp_dir=pip_compile.isolation):
55 | result = runner.invoke(cli=cli)
56 | assert result.exit_code == 0
57 | assert "hatch-pip-compile: Targeting environments: default" in result.output
58 | assert (
59 | "hatch-pip-compile: Running `hatch env run --env default -- python --version`"
60 | in result.output
61 | )
62 |
63 |
64 | def test_cli_bad_env(pip_compile: PipCompileFixture) -> None:
65 | """
66 | Test the full CLI with a non-existent environment
67 | """
68 | runner = CliRunner()
69 | with runner.isolated_filesystem(temp_dir=pip_compile.isolation):
70 | result = runner.invoke(cli=cli, args=["bad_env"])
71 | assert result.exit_code != 0
72 | assert "error" in result.output.lower()
73 | assert (
74 | "The following environments are not supported or unknown: bad_env. "
75 | "Supported environments are: default, docs, lint, misc, test"
76 | ) in result.output
77 |
78 |
79 | def test_cli_test_env(pip_compile: PipCompileFixture) -> None:
80 | """
81 | Test the full CLI with the `test` argument
82 | """
83 | runner = CliRunner()
84 | with runner.isolated_filesystem(temp_dir=pip_compile.isolation):
85 | result = runner.invoke(cli=cli, args=["test"])
86 | assert result.exit_code == 0
87 | assert "hatch-pip-compile: Targeting environments: test" in result.output
88 | assert (
89 | "hatch-pip-compile: Running `hatch env run --env test -- python --version`"
90 | in result.output
91 | )
92 |
93 |
94 | def test_cli_all(pip_compile: PipCompileFixture) -> None:
95 | """
96 | Test the full CLI with the `--all` argument
97 | """
98 | runner = CliRunner()
99 | with runner.isolated_filesystem(temp_dir=pip_compile.isolation):
100 | result = runner.invoke(cli=cli, args=["--all"])
101 | assert result.exit_code == 0
102 | assert (
103 | "hatch-pip-compile: Targeting environments: default, docs, lint, misc, test"
104 | in result.output
105 | )
106 |
107 |
108 | def test_cli_upgrade(pip_compile: PipCompileFixture) -> None:
109 | """
110 | Test the full CLI with the `--upgrade` argument
111 | """
112 | runner = CliRunner()
113 | with runner.isolated_filesystem(temp_dir=pip_compile.isolation):
114 | result = runner.invoke(cli=cli, args=["--upgrade"])
115 | assert result.exit_code == 0
116 | assert "hatch-pip-compile: Upgrading all dependencies" in result.output
117 |
118 |
119 | def test_cli_upgrade_packages(pip_compile: PipCompileFixture) -> None:
120 | """
121 | Test the full CLI with the `--upgrade-package` argument
122 | """
123 | runner = CliRunner()
124 | with runner.isolated_filesystem(temp_dir=pip_compile.isolation):
125 | result = runner.invoke(
126 | cli=cli, args=["--upgrade-package", "requests", "--upgrade-package", "urllib3"]
127 | )
128 | assert result.exit_code == 0
129 | assert "hatch-pip-compile: Upgrading packages: requests, urllib3" in result.output
130 |
131 |
132 | def test_cli_upgrade_test(pip_compile: PipCompileFixture) -> None:
133 | """
134 | Test the full CLI with the `--upgrade` argument for the `test` environment
135 | """
136 | runner = CliRunner()
137 | with runner.isolated_filesystem(temp_dir=pip_compile.isolation):
138 | result = runner.invoke(cli=cli, args=["test", "--upgrade"])
139 | assert result.exit_code == 0
140 | assert "hatch-pip-compile: Upgrading all dependencies" in result.output
141 | assert "hatch-pip-compile: Targeting environments: test" in result.output
142 |
143 |
144 | def test_command_runner_supported_environments(
145 | monkeypatch: pytest.MonkeyPatch,
146 | pip_compile: PipCompileFixture,
147 | ) -> None:
148 | """
149 | Test the `supported_environments` attribute
150 | """
151 | with pip_compile.chdir():
152 | command_runner = HatchCommandRunner(
153 | environments=["test"],
154 | upgrade=True,
155 | upgrade_packages=[],
156 | )
157 | assert command_runner.supported_environments == {"default", "test", "lint", "docs", "misc"}
158 |
159 |
160 | def test_command_runner_non_supported_environments(
161 | monkeypatch: pytest.MonkeyPatch,
162 | pip_compile: PipCompileFixture,
163 | ) -> None:
164 | """
165 | Test that a bad environment raises a `BadParameter` exception
166 | """
167 | with pip_compile.chdir():
168 | with pytest.raises(
169 | click.BadParameter,
170 | match=(
171 | "The following environments are not supported or unknown: bad_env. "
172 | "Supported environments are: default, docs, lint, misc, test"
173 | ),
174 | ):
175 | _ = HatchCommandRunner(
176 | environments=["bad_env"],
177 | upgrade=True,
178 | upgrade_packages=[],
179 | )
180 |
--------------------------------------------------------------------------------
/tests/test_installer.py:
--------------------------------------------------------------------------------
1 | """
2 | Installation Tests
3 | """
4 |
5 | from unittest.mock import Mock
6 |
7 | from tests.conftest import PipCompileFixture
8 |
9 |
10 | def test_pip_install_dependencies(mock_check_command: Mock, pip_compile: PipCompileFixture) -> None:
11 | """
12 | Assert the `pip` installation command is called with the expected arguments
13 | """
14 | pip_compile.default_environment.create()
15 | pip_compile.default_environment.installer.install_dependencies()
16 | expected_call = [
17 | "python",
18 | "-u",
19 | "-m",
20 | "pip",
21 | "install",
22 | "--disable-pip-version-check",
23 | "--no-python-version-warning",
24 | "-q",
25 | "--requirement",
26 | ]
27 | call_args = list(mock_check_command.call_args)[0][0][:-1]
28 | assert call_args == expected_call
29 |
--------------------------------------------------------------------------------
/tests/test_integration_cli.py:
--------------------------------------------------------------------------------
1 | """
2 | Integration Tests using the CLI
3 | """
4 |
5 | import platform
6 |
7 | import pytest
8 |
9 | from hatch_pip_compile.exceptions import HatchPipCompileError
10 | from tests.conftest import PipCompileFixture, installer_param, resolver_param
11 |
12 |
13 | @installer_param
14 | @resolver_param
15 | @pytest.mark.parametrize("environment_name", ["default", "test", "lint", "docs", "misc"])
16 | def test_invoke_environment_creates_env(
17 | pip_compile: PipCompileFixture, environment_name: str, resolver: str, installer: str
18 | ) -> None:
19 | """
20 | Test using the CLI runner
21 | """
22 | if installer == "pip-sync" and platform.system().lower() == "windows":
23 | pytest.skip("pip-sync + CLI runner not supported on Windows")
24 | environment = pip_compile.update_environment_resolver(
25 | environment=environment_name, resolver=resolver
26 | )
27 | environment = pip_compile.update_environment_installer(
28 | environment=environment, installer=installer
29 | )
30 | assert not pip_compile.virtualenv_exists(environment=environment)
31 | result = pip_compile.invoke_environment(environment=environment)
32 | assert result.exit_code == 0
33 | assert pip_compile.virtualenv_exists(environment=environment)
34 |
35 |
36 | def test_missing_lockfile_created(pip_compile: PipCompileFixture) -> None:
37 | """
38 | Running the CLI without a lockfile creates one
39 | """
40 | environment = pip_compile.default_environment
41 | environment.piptools_lock_file.unlink()
42 | assert not environment.piptools_lock_file.exists()
43 | result = pip_compile.invoke_environment(environment=environment)
44 | assert result.exit_code == 0
45 | assert environment.piptools_lock_file.exists()
46 | assert pip_compile.virtualenv_exists(environment=environment)
47 |
48 |
49 | def test_constraint_env_created(pip_compile: PipCompileFixture) -> None:
50 | """
51 | Running the CLI with a constraint env creates one
52 | """
53 | environment = pip_compile.test_environment
54 | environment.piptools_lock_file.unlink()
55 | environment.constraint_env.piptools_lock_file.unlink()
56 | result = pip_compile.invoke_environment(environment=environment)
57 | assert result.exit_code == 0
58 | assert environment.piptools_lock_file.exists()
59 | assert environment.constraint_env.piptools_lock_file.exists()
60 | assert environment.virtual_env.directory.exists()
61 | assert environment.constraint_env.virtual_env.directory.exists()
62 |
63 |
64 | def test_missing_lockfile_after_prepared(pip_compile: PipCompileFixture) -> None:
65 | """
66 | After an environment is prepared the lockfile is deleted and recreated the next time
67 | """
68 | environment = pip_compile.default_environment
69 | # Create the environment the first time
70 | result = pip_compile.invoke_environment(environment=environment)
71 | assert result.exit_code == 0
72 | # Delete the lockfile
73 | assert environment.piptools_lock_file.exists()
74 | environment.piptools_lock_file.unlink()
75 | assert not environment.piptools_lock_file.exists()
76 | # Run the environment again
77 | result = pip_compile.invoke_environment(
78 | environment=environment,
79 | )
80 | assert result.exit_code == 0
81 | # Assert the lockfile was recreated
82 | assert environment.piptools_lock_file.exists()
83 |
84 |
85 | @resolver_param
86 | @pytest.mark.parametrize("environment_name", ["default", "test", "lint"])
87 | def test_pip_compile_disable_cli(
88 | pip_compile: PipCompileFixture, environment_name: str, resolver: str
89 | ) -> None:
90 | """
91 | Test that the `PIP_COMPILE_DISABLE` environment variable raises an error
92 | """
93 | environment = pip_compile.update_environment_resolver(
94 | environment=environment_name, resolver=resolver
95 | )
96 | environment.piptools_lock_file.unlink(missing_ok=True)
97 | result = pip_compile.invoke_environment(
98 | environment=environment,
99 | env={"PIP_COMPILE_DISABLE": "1"},
100 | )
101 | assert result.exit_code == 1
102 | assert isinstance(result.exception, HatchPipCompileError)
103 |
104 |
105 | def test_prune_removes_all_environments(pip_compile: PipCompileFixture) -> None:
106 | """
107 | Assert that running `hatch env prune` removes all environments
108 | """
109 | pip_compile.default_environment.create()
110 | pip_compile.test_environment.create()
111 | assert pip_compile.default_environment.virtual_env.directory.exists()
112 | assert pip_compile.test_environment.virtual_env.directory.exists()
113 | result = pip_compile.cli_invoke(args=["env", "prune"])
114 | assert result.exit_code == 0
115 | assert not pip_compile.default_environment.virtual_env.directory.exists()
116 | assert not pip_compile.test_environment.virtual_env.directory.exists()
117 |
118 |
119 | @installer_param
120 | @resolver_param
121 | def test_add_new_dependency(pip_compile: PipCompileFixture, installer: str, resolver: str) -> None:
122 | """
123 | Create a new environment, assert that it exists without the `requests` package,
124 | then add the `requests` package to the environment, assert that it is installed.
125 | """
126 | if platform.system().lower() == "windows" and installer == "pip-sync":
127 | pytest.skip("pip-sync + CLI runner not supported on Windows")
128 | environment = pip_compile.default_environment
129 | assert not environment.virtual_env.directory.exists()
130 | pip_compile.update_environment_resolver(environment=environment, resolver=resolver)
131 | pip_compile.update_environment_installer(environment=environment, installer=installer)
132 | result = pip_compile.invoke_environment(environment=environment)
133 | assert result.exit_code == 0
134 | if result.exit_code != 0:
135 | raise result.exception
136 | assert environment.virtual_env.directory.exists()
137 | assert not pip_compile.is_installed(environment=environment, package="requests")
138 | assert "requests" not in environment.piptools_lock_file.read_text()
139 | pip_compile.toml_doc["project"]["dependencies"] += ["requests"]
140 | pip_compile.update_pyproject()
141 | new_result = pip_compile.invoke_environment(environment=environment)
142 | if new_result.exit_code != 0:
143 | raise new_result.exception
144 | assert "requests" in environment.piptools_lock_file.read_text()
145 | assert pip_compile.is_installed(environment=environment, package="requests")
146 |
147 |
148 | @installer_param
149 | @resolver_param
150 | def test_add_new_dependency_constraint_env(
151 | pip_compile: PipCompileFixture, installer: str, resolver: str
152 | ) -> None:
153 | """
154 | Test dependency workflow in a constraint environment
155 | """
156 | if platform.system().lower() == "windows" and installer == "pip-sync":
157 | pytest.skip("pip-sync + CLI runner not supported on Windows")
158 | environment = pip_compile.default_environment
159 | constraint_env = pip_compile.test_environment
160 | # Start with a clean slate, no environments
161 | assert not pip_compile.virtualenv_exists(environment=environment)
162 | assert not pip_compile.virtualenv_exists(environment=constraint_env)
163 | pip_compile.update_environment_resolver(environment=environment, resolver=resolver)
164 | pip_compile.update_environment_installer(environment=environment, installer=installer)
165 | # Invoke the constraint environment first. The default environment should not exist yet
166 | result = pip_compile.invoke_environment(environment=constraint_env)
167 | if result.exit_code != 0:
168 | raise result.exception
169 | assert not pip_compile.virtualenv_exists(environment=environment)
170 | assert pip_compile.is_installed(environment=constraint_env, package="pytest")
171 | assert "requests" not in environment.piptools_lock_file.read_text()
172 | assert not pip_compile.is_installed(environment=constraint_env, package="requests")
173 | # Now add the `requests` package to the default environment, and invoke the constraint env
174 | # The `requests` package should be installed in both environments and both lockfiles updated
175 | pip_compile.toml_doc["project"]["dependencies"] += ["requests"]
176 | pip_compile.update_pyproject()
177 | pip_compile.invoke_environment(environment=constraint_env)
178 | assert "requests" in environment.piptools_lock_file.read_text()
179 | assert "requests" in constraint_env.piptools_lock_file.read_text()
180 | assert pip_compile.is_installed(environment=environment, package="requests")
181 | assert pip_compile.is_installed(environment=constraint_env, package="requests")
182 |
--------------------------------------------------------------------------------
/tests/test_lock.py:
--------------------------------------------------------------------------------
1 | """
2 | Testing the `lock` module
3 | """
4 | from textwrap import dedent
5 |
6 | from packaging.requirements import Requirement
7 | from packaging.version import Version
8 |
9 | from tests.conftest import PipCompileFixture
10 |
11 |
12 | def test_lockfile_python_version(
13 | pip_compile: PipCompileFixture,
14 | ):
15 | """
16 | Test the expected Python version from the lockfiles
17 | """
18 | assert pip_compile.default_environment.piptools_lock.lock_file_version == Version("3.11")
19 | assert pip_compile.test_environment.piptools_lock.lock_file_version == Version("3.11")
20 |
21 |
22 | def test_lockfile_dependencies(
23 | pip_compile: PipCompileFixture,
24 | ):
25 | """
26 | Test the expected dependencies from reading the lockfiles
27 | """
28 | assert set(pip_compile.default_environment.piptools_lock.read_header_requirements()) == {
29 | Requirement("hatch")
30 | }
31 | assert set(pip_compile.test_environment.piptools_lock.read_header_requirements()) == {
32 | Requirement("pytest"),
33 | Requirement("pytest-cov"),
34 | Requirement("hatch"),
35 | }
36 |
37 |
38 | def test_compare_requirements_match(pip_compile: PipCompileFixture):
39 | """
40 | Test the `compare_requirements` method with a match
41 | """
42 | default_check = pip_compile.default_environment.piptools_lock.compare_requirements(
43 | requirements=[Requirement("hatch")],
44 | )
45 | assert default_check is True
46 |
47 |
48 | def test_compare_requirements_mismatch(pip_compile: PipCompileFixture):
49 | """
50 | Test the `compare_requirements` method with a mismatch
51 | """
52 | test_check = pip_compile.test_environment.piptools_lock.compare_requirements(
53 | requirements=[Requirement("hatch")],
54 | )
55 | assert test_check is False
56 |
57 |
58 | def test_read_lock_requirements(pip_compile: PipCompileFixture) -> None:
59 | """
60 | Test the `read_lock_requirements` method
61 | """
62 | linting_env = pip_compile.reload_environment("lint")
63 | requirements = linting_env.piptools_lock.read_lock_requirements()
64 | string_requirements = set(map(str, requirements))
65 | assert string_requirements == {
66 | "mypy==1.7.1",
67 | "mypy-extensions==1.0.0",
68 | "ruff==0.1.6",
69 | "typing-extensions==4.8.0",
70 | }
71 |
72 |
73 | def test_replace_temporary_lockfile_windows(pip_compile: PipCompileFixture) -> None:
74 | """
75 | Regex Replace Temporary File Path: Windows
76 | """
77 | lock_raw = r"""
78 | httpx==0.22.0
79 | # via -r C:\Users\xxx\AppData\Local\Temp\tmp_kn984om\default.in
80 | """
81 | lock_body = dedent(lock_raw).strip()
82 | cleaned_text = pip_compile.default_environment.piptools_lock.replace_temporary_lockfile(
83 | lock_body
84 | )
85 | expected_raw = r"""
86 | httpx==0.22.0
87 | # via hatch.envs.default
88 | """
89 | assert cleaned_text == dedent(expected_raw).strip()
90 |
91 |
92 | def test_replace_temporary_lockfile_unix(pip_compile: PipCompileFixture) -> None:
93 | """
94 | Regex Replace Temporary File Path: Unix
95 | """
96 | lock_raw = r"""
97 | httpx==0.22.0
98 | # via -r /tmp/tmp_kn984om/default.in
99 | """
100 | lock_body = dedent(lock_raw).strip()
101 | cleaned_text = pip_compile.default_environment.piptools_lock.replace_temporary_lockfile(
102 | lock_body
103 | )
104 | expected_raw = r"""
105 | httpx==0.22.0
106 | # via hatch.envs.default
107 | """
108 | assert cleaned_text == dedent(expected_raw).strip()
109 |
--------------------------------------------------------------------------------
/tests/test_plugin.py:
--------------------------------------------------------------------------------
1 | """
2 | Plugin tests.
3 | """
4 |
5 | from unittest.mock import Mock
6 |
7 | import pytest
8 |
9 | from hatch_pip_compile.exceptions import HatchPipCompileError
10 | from hatch_pip_compile.resolver import PipCompileResolver
11 | from tests.conftest import PipCompileFixture
12 |
13 |
14 | def test_lockfile_path(
15 | pip_compile: PipCompileFixture,
16 | ) -> None:
17 | """
18 | Test the default lockfile paths
19 | """
20 | assert (
21 | pip_compile.default_environment.piptools_lock_file
22 | == pip_compile.isolation / "requirements.txt"
23 | )
24 | assert (
25 | pip_compile.test_environment.piptools_lock_file
26 | == pip_compile.isolation / "requirements" / "requirements-test.txt"
27 | )
28 |
29 |
30 | def test_piptools_constraints_file(
31 | pip_compile: PipCompileFixture,
32 | ) -> None:
33 | """
34 | Test constraints paths
35 | """
36 | assert pip_compile.default_environment.piptools_constraints_file is None
37 | assert (
38 | pip_compile.test_environment.piptools_constraints_file
39 | == pip_compile.default_environment.piptools_lock_file
40 | )
41 |
42 |
43 | def test_expected_dependencies(pip_compile: PipCompileFixture) -> None:
44 | """
45 | Test expected dependencies from `PipCompileEnvironment`
46 | """
47 | assert set(pip_compile.default_environment.dependencies) == {"hatch"}
48 | assert set(pip_compile.test_environment.dependencies) == {"pytest", "pytest-cov", "hatch"}
49 |
50 |
51 | def test_lockfile_up_to_date_missing(pip_compile: PipCompileFixture) -> None:
52 | """
53 | Test the `lockfile_up_to_date` property when the lockfile is missing
54 | """
55 | pip_compile.default_environment.piptools_lock_file.unlink()
56 | assert pip_compile.default_environment.lockfile_up_to_date is False
57 | assert pip_compile.default_environment.dependencies_in_sync() is False
58 |
59 |
60 | def test_lockfile_up_to_date_empty(pip_compile: PipCompileFixture) -> None:
61 | """
62 | Test the `lockfile_up_to_date` property when the lockfile is empty
63 | """
64 | pip_compile.default_environment.piptools_lock_file.write_text("")
65 | assert pip_compile.default_environment.lockfile_up_to_date is False
66 | assert pip_compile.default_environment.dependencies_in_sync() is False
67 |
68 |
69 | def test_lockfile_up_to_date_mismatch(pip_compile: PipCompileFixture) -> None:
70 | """
71 | Test the `lockfile_up_to_date` property when the lockfile is mismatched
72 | """
73 | lock_text = pip_compile.default_environment.piptools_lock_file.read_text()
74 | lock_text = lock_text.replace("# - hatch", "#")
75 | pip_compile.default_environment.piptools_lock_file.write_text(lock_text)
76 | assert pip_compile.default_environment.lockfile_up_to_date is False
77 |
78 |
79 | def test_pip_compile_cli(mock_check_command: Mock, pip_compile: PipCompileFixture) -> None:
80 | """
81 | Test the `pip_compile_cli` method is called with the expected arguments
82 | """
83 | pip_compile.default_environment.pip_compile_cli()
84 | expected_call = [
85 | "python",
86 | "-m",
87 | "piptools",
88 | "compile",
89 | "--quiet",
90 | "--no-header",
91 | "--resolver=backtracking",
92 | "--strip-extras",
93 | "--output-file",
94 | ]
95 | call_args = list(mock_check_command.call_args)[0][0][:-2]
96 | assert call_args == expected_call
97 |
98 |
99 | def test_env_var_disabled(pip_compile: PipCompileFixture, monkeypatch: pytest.MonkeyPatch) -> None:
100 | """
101 | Test the `lockfile_up_to_date` property when the lockfile is empty
102 | """
103 | monkeypatch.setenv("PIP_COMPILE_DISABLE", "1")
104 | with pytest.raises(HatchPipCompileError, match="attempted to run a lockfile update"):
105 | pip_compile.default_environment.pip_compile_cli()
106 |
107 |
108 | @pytest.mark.parametrize("environment_name", ["default", "misc", "docs"])
109 | def test_constraint_env_self(pip_compile: PipCompileFixture, environment_name: str) -> None:
110 | """
111 | Test the value of the constraint env b/w the default and test environments
112 | """
113 | environment = pip_compile.reload_environment(environment=environment_name)
114 | assert environment.constraint_env is environment
115 |
116 |
117 | @pytest.mark.parametrize("environment_name", ["test"])
118 | def test_constraint_env_other(pip_compile: PipCompileFixture, environment_name: str) -> None:
119 | """
120 | Test the value of the constraint env b/w the default and test environments
121 | """
122 | environment = pip_compile.reload_environment(environment=environment_name)
123 | assert environment.constraint_env.name == pip_compile.default_environment.name
124 |
125 |
126 | @pytest.mark.parametrize("environment_name", ["default", "docs", "misc"])
127 | def test_prepare_environment(pip_compile: PipCompileFixture, environment_name: str) -> None:
128 | """
129 | Test the `prepare_environment` method
130 | """
131 | environment = pip_compile.reload_environment(environment=environment_name)
132 | environment.prepare_environment()
133 | if environment.dependencies:
134 | assert environment.piptools_lock_file.exists()
135 | else:
136 | assert not environment.piptools_lock_file.exists()
137 | assert environment.dependencies_in_sync() is True
138 | assert environment.lockfile_up_to_date is True
139 |
140 |
141 | def test_resolver_instance_default(pip_compile: PipCompileFixture) -> None:
142 | """
143 | Test the `pip-compile-resolver` option on default resolver
144 | """
145 | assert isinstance(pip_compile.default_environment.resolver, PipCompileResolver)
146 |
147 |
148 | def test_resolver_instance_pip_compile(pip_compile: PipCompileFixture) -> None:
149 | """
150 | Test that the `PipCompileResolver` is used
151 | """
152 | pip_compile.toml_doc["tool"]["hatch"]["envs"]["default"]["pip-compile-resolver"] = "pip-compile"
153 | pip_compile.update_pyproject()
154 | environment = pip_compile.reload_environment("default")
155 | assert isinstance(environment.resolver, PipCompileResolver)
156 |
--------------------------------------------------------------------------------