Full Code of jazzband/pip-tools for AI

main ea032fe82279 cached
140 files
617.0 KB
160.6k tokens
612 symbols
1 requests
Download .txt
Showing preview only (654K chars total). Download the full file or copy to clipboard to get everything.
Repository: jazzband/pip-tools
Branch: main
Commit: ea032fe82279
Files: 140
Total size: 617.0 KB

Directory structure:
gitextract_04gc2qn3/

├── .bandit
├── .codecov.yml
├── .coveragerc
├── .flake8
├── .git_archival.txt
├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   └── feature-request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── actions/
│   │   └── cache-keys/
│   │       └── action.yml
│   ├── chronographer.yml
│   ├── reusables/
│   │   └── tox-dev/
│   │       └── workflow/
│   │           └── reusable-tox/
│   │               └── hooks/
│   │                   └── post-tox-run/
│   │                       └── action.yml
│   └── workflows/
│       ├── ci.yml
│       ├── cron.yml
│       ├── release.yml
│       └── reusable-qa.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .pre-commit-hooks.yaml
├── .pymarkdown.yml
├── .readthedocs.yaml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── MANIFEST.in
├── README.md
├── changelog.d/
│   ├── .draft_changelog_partial.md
│   ├── .gitignore
│   ├── .towncrier_template.md.jinja
│   ├── 1142.feature.md
│   ├── 2318.contrib.md
│   ├── 2327.contrib.md
│   ├── 2343.contrib.md
│   └── README.md
├── docs/
│   ├── .gitignore
│   ├── changelog.md
│   ├── cli/
│   │   ├── index.md
│   │   ├── pip-compile.md
│   │   └── pip-sync.md
│   ├── conf.py
│   ├── contributing.md
│   ├── index.md
│   ├── pkg/
│   │   └── .gitignore
│   ├── requirements.in
│   └── requirements.txt
├── examples/
│   ├── django.in
│   ├── flask.in
│   ├── hypothesis.in
│   ├── protection.in
│   ├── readme/
│   │   ├── constraints.txt
│   │   └── pyproject.toml
│   └── sentry.in
├── piptools/
│   ├── __init__.py
│   ├── __main__.py
│   ├── _compat/
│   │   ├── __init__.py
│   │   ├── _tomllib_compat.py
│   │   ├── path_compat.py
│   │   ├── pip_compat.py
│   │   └── tempfile_compat.py
│   ├── _internal/
│   │   ├── __init__.py
│   │   ├── _pip_api/
│   │   │   ├── __init__.py
│   │   │   ├── cli_options.py
│   │   │   ├── install_requirements.py
│   │   │   ├── package_finder.py
│   │   │   └── pip_version.py
│   │   └── _subprocess.py
│   ├── build.py
│   ├── cache.py
│   ├── exceptions.py
│   ├── locations.py
│   ├── logging.py
│   ├── py.typed
│   ├── repositories/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── local.py
│   │   └── pypi.py
│   ├── resolver.py
│   ├── scripts/
│   │   ├── __init__.py
│   │   ├── _deprecations.py
│   │   ├── compile.py
│   │   ├── options.py
│   │   └── sync.py
│   ├── sync.py
│   ├── utils.py
│   └── writer.py
├── pyproject.toml
├── tests/
│   ├── __init__.py
│   ├── conftest.py
│   ├── constants.py
│   ├── test_build.py
│   ├── test_cache.py
│   ├── test_circular_imports.py
│   ├── test_cli_compile.py
│   ├── test_cli_sync.py
│   ├── test_data/
│   │   ├── fake-editables.json
│   │   ├── fake-index.json
│   │   ├── minimal_wheels/
│   │   │   ├── small_fake_a-0.1-py2.py3-none-any.whl
│   │   │   ├── small_fake_a-0.2-py2.py3-none-any.whl
│   │   │   ├── small_fake_a-0.3b1-py2.py3-none-any.whl
│   │   │   ├── small_fake_b-0.1-py2.py3-none-any.whl
│   │   │   ├── small_fake_b-0.2-py2.py3-none-any.whl
│   │   │   ├── small_fake_b-0.3-py2.py3-none-any.whl
│   │   │   ├── small_fake_multi_arch-0.1-py2.py3-none-manylinux1_i686.whl
│   │   │   ├── small_fake_multi_arch-0.1-py2.py3-none-manylinux1_x86_64.whl
│   │   │   ├── small_fake_multi_arch-0.1-py2.py3-none-win32.whl
│   │   │   ├── small_fake_with_deps-0.1-py2.py3-none-any.whl
│   │   │   ├── small_fake_with_deps_and_sub_deps-0.1-py2.py3-none-any.whl
│   │   │   └── small_fake_with_unpinned_deps-0.1-py2.py3-none-any.whl
│   │   └── packages/
│   │       ├── fake_with_deps/
│   │       │   ├── fake_with_deps/
│   │       │   │   └── __init__.py
│   │       │   └── pyproject.toml
│   │       ├── small_fake_a/
│   │       │   └── setup.py
│   │       ├── small_fake_with_build_deps/
│   │       │   ├── backend/
│   │       │   │   └── backend.py
│   │       │   ├── pyproject.toml
│   │       │   └── setup.py
│   │       ├── small_fake_with_deps/
│   │       │   └── setup.py
│   │       ├── small_fake_with_deps_and_sub_deps/
│   │       │   └── setup.py
│   │       ├── small_fake_with_pyproject/
│   │       │   └── pyproject.toml
│   │       ├── small_fake_with_subdir/
│   │       │   └── subdir/
│   │       │       └── setup.py
│   │       └── small_fake_with_unpinned_deps/
│   │           └── setup.py
│   ├── test_fake_index.py
│   ├── test_logging.py
│   ├── test_minimal_upgrade.py
│   ├── test_pip_compat.py
│   ├── test_repository_local.py
│   ├── test_repository_pypi.py
│   ├── test_resolver.py
│   ├── test_sync.py
│   ├── test_top_level_editable.py
│   ├── test_utils.py
│   ├── test_writer.py
│   ├── unit/
│   │   └── _internal/
│   │       ├── pip_api/
│   │       │   ├── test_cli_options.py
│   │       │   ├── test_install_requirements.py
│   │       │   ├── test_package_finder.py
│   │       │   └── test_pip_version.py
│   │       └── test_subprocess.py
│   └── utils.py
├── towncrier.toml
└── tox.ini

================================================
FILE CONTENTS
================================================

================================================
FILE: .bandit
================================================
[bandit]
exclude: tests,.tox,.eggs,.venv,.git
skips: B101


================================================
FILE: .codecov.yml
================================================
---

codecov:
  notify:
    manual_trigger: true  # prevent notifications until we notify Codecov

  require_ci_to_pass: false

comment: false # avoid spamming reviews

...


================================================
FILE: .coveragerc
================================================
[run]
plugins = covdefaults
omit =
    piptools/_compat/*

[report]
include = piptools/*, tests/*
fail_under = 99


================================================
FILE: .flake8
================================================
[flake8]
max-line-length = 100
# E203 conflicts with PEP8; see https://github.com/psf/black#slices
extend-ignore = E203

# flake8-pytest-style
# PT001:
pytest-fixture-no-parentheses = true
# PT006:
pytest-parametrize-names-type = tuple
# PT007:
pytest-parametrize-values-type = tuple
pytest-parametrize-values-row-type = tuple
# PT023:
pytest-mark-no-parentheses = true

# flake8-typing-as-t
# TYT02:
typing-as-t-imported-name = _t


================================================
FILE: .git_archival.txt
================================================
node: $Format:%H$
node-date: $Format:%cI$
describe-name: $Format:%(describe:tags=true,match=v[0-9]*[0-9])$


================================================
FILE: .gitattributes
================================================
# fill in placeholders when `git archive` is used, setuptools-scm support
.git_archival.txt  export-subst


================================================
FILE: .github/CODEOWNERS
================================================
/.github/ @jazzband/pip-tools-leads
/tox.ini @jazzband/pip-tools-leads


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---

name: Bug report
about: Create a report to help us improve

---

<!-- Describe the issue briefly here. -->

#### Environment Versions

1. OS Type
1. Python version: `$ python -V`
1. pip version: `$ pip --version`
1. pip-tools version: `$ pip-compile --version`

#### Steps to replicate

1. ...
2. ...
3. ...

#### Expected result

...

#### Actual result

...


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.md
================================================
---

name: Feature request
about: Suggest an idea for this project

---

#### What's the problem this feature will solve?

<!--
What are you trying to do, that you are unable to achieve with pip-tools as it
currently stands?
-->

#### Describe the solution you'd like

<!-- A clear and concise description of what you want to happen. -->

<!--
Provide examples of real-world use cases that this would enable and how it
solves the problem described above.
-->

#### Alternative Solutions

<!--
Have you tried to workaround the problem using pip-tools or other tools? Or a
different approach to solving this issue? Please elaborate here.
-->

#### Additional context

<!-- Add any other context, links, etc. about the feature here. -->


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--- Describe the changes here. --->

##### Contributor checklist

- [ ] Included tests for the changes.
- [ ] A change note is created in `changelog.d/` (see [`changelog.d/README.md`]
      for instructions) or the PR text says "no changelog needed".

[`changelog.d/README.md`]:
https://github.com/jazzband/pip-tools/blob/main/changelog.d/#readme

##### Maintainer checklist

- [ ] If no changelog is needed, apply the `bot:chronographer:skip` label.
- [ ] Assign the PR to an existing or new milestone for the target version
      (following Semantic Versioning).


================================================
FILE: .github/actions/cache-keys/action.yml
================================================
---

name: placeholder
description: placeholder

outputs:
  cache-key-for-dep-files:
    description: >-
      A cache key string derived from the dependency declaration files.
    value: ${{ steps.calc-cache-key-files.outputs.files-hash-key }}

runs:
  using: composite
  steps:
  - name: >-
      Calculate dependency files' combined hash value
      for use in the cache key
    id: calc-cache-key-files
    run: |
      from os import environ
      from pathlib import Path

      FILE_APPEND_MODE = 'a'

      files_derived_hash = '${{
          hashFiles(
            'tox.ini',
            'pyproject.toml',
            '.pre-commit-config.yaml',
            'pytest.ini',
            'dependencies/**',
            'dependencies/*/**',
            'setup.cfg'
          )
      }}'

      print(f'Computed file-derived hash is {files_derived_hash}.')

      with Path(environ['GITHUB_OUTPUT']).open(
              mode=FILE_APPEND_MODE,
      ) as outputs_file:
          print(
              f'files-hash-key={files_derived_hash}',
              file=outputs_file,
          )
    shell: python

...


================================================
FILE: .github/chronographer.yml
================================================
branch-protection-check-name: Change log entry
action-hints:
  check-title-prefix: "Chronographer: "
  external-docs-url: https://pip-tools.rtfd.io/en/latest/contributing/#adding-change-notes-with-prs
  inline-markdown: |
    See [the changelog contribution docs] for news fragment authoring gotchas.

    [the changelog contribution docs]: https://pip-tools.rtfd.io/en/latest/contributing/#adding-change-notes-with-prs
enforce-name:
  suffix: .md


================================================
FILE: .github/reusables/tox-dev/workflow/reusable-tox/hooks/post-tox-run/action.yml
================================================
---

inputs:
  calling-job-context:
    description: A JSON with the calling job inputs
    type: string
  current-job-steps:
    description: >-
      The `$ {{ steps }}` context passed from the reusable workflow's
      tox job encoded as a JSON string. The caller passes it this input
      as follows:
      `current-job-steps: $ {{ toJSON(steps) }}`.
    type: string
  job-dependencies-context:
    default: >-
      {}
    description: >-
      The `$ {{ needs }}` context passed from the calling workflow
      encoded as a JSON string. The caller is expected to form this
      input as follows:
      `job-dependencies-context: $ {{ toJSON(needs) }}`.
    required: false
    type: string

runs:
  using: composite
  steps:
  - name: Verify that the artifacts with expected names got created
    if: fromJSON(inputs.calling-job-context).toxenv == 'build-dists'
    run: >
      # Verify that the artifacts with expected names got created


      ls -1
      'dist/${{
        fromJSON(
          inputs.job-dependencies-context
        ).pre-setup.outputs.sdist-artifact-name
      }}'
      'dist/${{
        fromJSON(
          inputs.job-dependencies-context
        ).pre-setup.outputs.wheel-artifact-name
      }}'
    shell: bash
  - name: Store the distribution packages
    if: fromJSON(inputs.calling-job-context).toxenv == 'build-dists'
    uses: actions/upload-artifact@v4
    with:
      name: >-
        ${{
          fromJSON(
            inputs.job-dependencies-context
          ).pre-setup.outputs.dists-artifact-name
        }}
      # NOTE: Exact expected file names are specified here
      # NOTE: as a safety measure — if anything weird ends
      # NOTE: up being in this dir or not all dists will be
      # NOTE: produced, this will fail the workflow.
      path: |
        dist/${{
          fromJSON(
            inputs.job-dependencies-context
          ).pre-setup.outputs.sdist-artifact-name
        }}
        dist/${{
          fromJSON(
            inputs.job-dependencies-context
          ).pre-setup.outputs.wheel-artifact-name
        }}
      retention-days: >-
        ${{
            fromJSON(
              fromJSON(
                inputs.job-dependencies-context
              ).pre-setup.outputs.release-requested
            )
            && 90
            || 30
        }}

...


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  merge_group:
  pull_request:
  push:
    branches:
      - main
    tags:
      - v*
  workflow_call:
    inputs:
      cpython-pip-version:
        description: >-
          A JSON string with pip versions
          to test against under CPython.
        required: false
        type: string
      cpython-versions:
        description: >-
          A JSON string with CPython versions
          to test against.
        required: false
        type: string
      release-version:
        description: >-
          Target PEP440-compliant version to release.
          Any leading `v` will be stripped off.
        required: false
        type: string
      release-committish:
        default: ''
        description: >-
          The commit to be released to PyPI and tagged
          in Git as `release-version`. Normally, you
          should keep this empty.
        type: string

    outputs:
      dists-artifact-name:
        description: Workflow artifact name containing dists.
        value: ${{ jobs.pre-setup.outputs.dists-artifact-name }}
      is-upstream-repository:
        description: >-
          A flag representing whether the workflow runs in the upstream
          repository or a fork.
        value: ${{ jobs.pre-setup.outputs.is-upstream-repository }}
      project-name:
        description: PyPI project name.
        value: ${{ jobs.pre-setup.outputs.project-name }}
      project-version:
        description: PyPI project version string.
        value: ${{ jobs.pre-setup.outputs.dist-version }}

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

env:
  FORCE_COLOR: 1 # Request colored output from CLI tools supporting it
  MYPY_FORCE_COLOR: 1 # MyPy's color enforcement
  PIP_DISABLE_PIP_VERSION_CHECK: 1
  PIP_NO_PYTHON_VERSION_WARNING: 1
  PIP_NO_WARN_SCRIPT_LOCATION: 1
  PRE_COMMIT_COLOR: 1
  PY_COLORS: 1 # Recognized by the `py` package, dependency of `pytest`
  TOX_PARALLEL_NO_SPINNER: 1
  TOX_TESTENV_PASSENV: >-
    FORCE_COLOR
    MYPY_FORCE_COLOR
    NO_COLOR
    PY_COLORS
    PYTEST_THEME
    PYTEST_THEME_MODE
    PRE_COMMIT_COLOR
  UPSTREAM_REPOSITORY_ID: >-
    5746963

jobs:
  pre-setup:
    name: ⚙️ Pre-set global build settings

    runs-on: ubuntu-latest

    timeout-minutes: 2  # network is slow sometimes when fetching from Git

    defaults:
      run:
        shell: python

    outputs:
      # NOTE: These aren't env vars because the `${{ env }}` context is
      # NOTE: inaccessible when passing inputs to reusable workflows.
      dists-artifact-name: python-package-distributions
      dist-version: >-
        ${{ steps.normalize-dist-version.outputs.dist-version }}
      project-name: ${{ steps.metadata.outputs.project-name }}
      release-requested: >-
        ${{
            steps.request-check.outputs.release-requested || false
        }}
      cache-key-for-dep-files: >-
        ${{ steps.calc-cache-key-files.outputs.cache-key-for-dep-files }}
      sdist-artifact-name: ${{ steps.artifact-name.outputs.sdist }}
      wheel-artifact-name: ${{ steps.artifact-name.outputs.wheel }}
      is-upstream-repository: >-
        ${{ toJSON(env.UPSTREAM_REPOSITORY_ID == github.repository_id) }}

    steps:
    - name: Switch to using Python 3.14 by default
      uses: actions/setup-python@v6
      with:
        python-version: 3.14
    - name: >-
        Mark the build as untagged '${{
            github.event.repository.default_branch
        }}' branch build
      id: untagged-check
      if: >-
        github.event_name == 'push' &&
        github.ref_type == 'branch' &&
        github.ref_name == github.event.repository.default_branch
      run: |
        from os import environ
        from pathlib import Path

        FILE_APPEND_MODE = 'a'

        with Path(environ['GITHUB_OUTPUT']).open(
                mode=FILE_APPEND_MODE,
        ) as outputs_file:
            print('is-untagged-devel=true', file=outputs_file)
    - name: Mark the build as "release request"
      id: request-check
      if: inputs.release-version != ''
      run: |
        from os import environ
        from pathlib import Path

        FILE_APPEND_MODE = 'a'

        with Path(environ['GITHUB_OUTPUT']).open(
                mode=FILE_APPEND_MODE,
        ) as outputs_file:
            print('release-requested=true', file=outputs_file)
    - name: Check out src from Git
      uses: actions/checkout@v4
      with:
        fetch-depth: >-
          ${{
            steps.request-check.outputs.release-requested == 'true'
            && 1 || 0
          }}
        ref: ${{ inputs.release-committish }}
    - name: Scan static PEP 621 core packaging metadata
      id: metadata
      run: |
        from os import environ
        from pathlib import Path
        from tomllib import loads as parse_toml_from_string

        FILE_APPEND_MODE = 'a'

        pyproject_toml_txt = Path('pyproject.toml').read_text()
        metadata = parse_toml_from_string(pyproject_toml_txt)['project']
        project_name = metadata["name"]

        with Path(environ['GITHUB_OUTPUT']).open(
                mode=FILE_APPEND_MODE,
        ) as outputs_file:
            print(f'project-name={project_name}', file=outputs_file)
    - name: >-
        Calculate dependency files' combined hash value
        for use in the cache key
      if: >-
        steps.request-check.outputs.release-requested != 'true'
      id: calc-cache-key-files
      uses: ./.github/actions/cache-keys
    - name: Set up pip cache
      if: >-
        steps.request-check.outputs.release-requested != 'true'
      uses: re-actors/cache-python-deps@release/v1
      with:
        cache-key-for-dependency-files: >-
          ${{ steps.calc-cache-key-files.outputs.cache-key-for-dep-files }}
    - name: Drop Git tags from HEAD for non-release requests
      if: >-
        steps.request-check.outputs.release-requested != 'true'
      run: >-
        git tag --points-at HEAD
        |
        xargs git tag --delete
      shell: bash -eEuxo pipefail {0}
    - name: Set up versioning prerequisites
      if: >-
        steps.request-check.outputs.release-requested != 'true'
      run: >-
        python -m
        pip install
        --user
        setuptools-scm
      shell: bash -eEuxo pipefail {0}
    - name: Set the current dist version from Git
      if: steps.request-check.outputs.release-requested != 'true'
      id: scm-version
      run: |
        from os import environ
        from pathlib import Path

        import setuptools_scm

        FILE_APPEND_MODE = 'a'

        ver = setuptools_scm.get_version(local_scheme='dirty-tag')
        with Path(environ['GITHUB_OUTPUT']).open(
                mode=FILE_APPEND_MODE,
        ) as outputs_file:
            print(f'dist-version={ver}', file=outputs_file)
            print(
                f'dist-version-for-filenames={ver.replace("+", "-")}',
                file=outputs_file,
            )
    - name: Normalize dist version
      id: normalize-dist-version
      run: |
        from os import environ
        from pathlib import Path

        FILE_APPEND_MODE = 'a'

        dist_version = "${{
            steps.request-check.outputs.release-requested == 'true'
            && inputs.release-version
            || steps.scm-version.outputs.dist-version
        }}".lstrip("v")

        with Path(environ['GITHUB_OUTPUT']).open(
                mode=FILE_APPEND_MODE,
        ) as outputs_file:
            print(
                f"dist-version={dist_version}",
                file=outputs_file,
            )
    - name: Set the expected dist artifact names
      id: artifact-name
      env:
        PROJECT_NAME: ${{ steps.metadata.outputs.project-name }}
      run: |
        from os import environ
        from pathlib import Path

        FILE_APPEND_MODE = 'a'

        whl_file_prj_base_name = environ['PROJECT_NAME'].replace('-', '_')
        sdist_file_prj_base_name = (
            whl_file_prj_base_name.
            replace('.', '_').
            lower()
        )
        dist_version = "${{ steps.normalize-dist-version.outputs.dist-version }}"

        with Path(environ['GITHUB_OUTPUT']).open(
                mode=FILE_APPEND_MODE,
        ) as outputs_file:
            print(
                f"sdist={sdist_file_prj_base_name !s}-{dist_version}.tar.gz",
                file=outputs_file,
            )
            print(
                f"wheel={whl_file_prj_base_name !s}-{dist_version}-py3-none-any.whl",
                file=outputs_file,
            )

  build:
    name: >-
      📦 Build dists
    needs:
    - pre-setup  # transitive, for accessing settings

    uses: tox-dev/workflow/.github/workflows/reusable-tox.yml@617ca35caa695c572377861016677905e58a328c  # yamllint disable-line rule:line-length
    with:
      cache-key-for-dependency-files: >-
        ${{ needs.pre-setup.outputs.cache-key-for-dep-files }}
      check-name: Build dists under 🐍3.12
      checkout-src-git-committish: >-
        ${{ inputs.release-committish }}
      checkout-src-git-fetch-depth: >-
        ${{
          fromJSON(needs.pre-setup.outputs.release-requested)
          && 1
          || 0
        }}
      job-dependencies-context: >-  # context for hooks
        ${{ toJSON(needs) }}
      python-version: 3.12
      runner-vm-os: ubuntu-latest
      timeout-minutes: 2
      toxenv: build-dists
      xfail: false

  linters:
    name: Linters
    uses: ./.github/workflows/reusable-qa.yml

  test:
    name: ${{ matrix.os }} / ${{ matrix.python-version }} / ${{ matrix.pip-version }}
    runs-on: ${{ matrix.os }}-latest
    timeout-minutes: 15
    strategy:
      fail-fast: false
      matrix:
        os:
          - Ubuntu
          - Windows
          - macOS
        python-version: >-
          ${{
            fromJSON(
              inputs.cpython-versions
              && inputs.cpython-versions
              ||
              '["3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"]'
            )
          }}
        pip-version: >-
          ${{
            fromJSON(
              inputs.cpython-pip-version
              && inputs.cpython-pip-version
              || '["supported", "lowest"]'
            )
          }}
    env:
      TOXENV: >-
        pip${{ matrix.pip-version }}${{
          !inputs.cpython-pip-version
          && '-coverage'
          || ''
        }}
    steps:
      - uses: actions/checkout@v5
      - name: Set up Python ${{ matrix.python-version }} from GitHub
        id: python-install
        if: "!endsWith(matrix.python-version, '-dev')"
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Set up Python ${{ matrix.python-version }} from deadsnakes
        if: endsWith(matrix.python-version, '-dev')
        uses: deadsnakes/action@v2.1.1
        with:
          python-version: ${{ matrix.python-version }}
      - name: Log python version info (${{ matrix.python-version }})
        run: python --version --version
      - name: Get pip cache dir
        id: pip-cache
        shell: bash
        run: |
          echo "dir=$(pip cache dir)" >> "${GITHUB_OUTPUT}"
      - name: Pip cache
        uses: actions/cache@v4
        with:
          path: ${{ steps.pip-cache.outputs.dir }}
          key: >-
            ${{ runner.os }}-pip-${{ hashFiles('setup.cfg') }}-${{
            hashFiles('pyproject.toml') }}-${{ hashFiles('tox.ini') }}-${{
            hashFiles('.pre-commit-config.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pip-
            ${{ runner.os }}-
      - name: Install test dependencies
        run: python -m pip install -U tox virtualenv
      - name: Prepare test environment
        # NOTE: `--parallel-live` is a workaround for the regression in
        # NOTE: the upstream tox project that made the
        # NOTE: `TOX_PARALLEL_NO_SPINNER=1` env var auto-enable parallelism
        # NOTE: and disable output from the tox environments.
        #
        # Ref: https://github.com/tox-dev/tox/issues/3193
        run: tox -vv --notest -p auto --parallel-live
      - name: Test pip ${{ matrix.pip-version }}
        # NOTE: `--parallel-live` is a workaround for the regression in
        # NOTE: the upstream tox project that made the
        # NOTE: `TOX_PARALLEL_NO_SPINNER=1` env var auto-enable parallelism
        # NOTE: and disable output from the tox environments.
        #
        # Ref: https://github.com/tox-dev/tox/issues/3193
        run: tox --skip-pkg-install --parallel-live
      - name: Re-run the failing tests with maximum verbosity
        if: >-
          !cancelled()
          && failure()
        run: >-  # `exit 1` makes sure that the job remains red with flaky runs
          python -Xutf8 -Im
          tox
          --parallel=auto
          --parallel-live
          --skip-missing-interpreters=false
          --skip-pkg-install
          -vvvvv
          --
          --continue-on-collection-errors
          --full-trace
          --last-failed
          ${{ !inputs.cpython-pip-version && '--no-cov' || '' }}
          --numprocesses=0
          --showlocals
          --trace-config
          -rA
          -vvvvv
          && exit 1
        shell: bash
      - name: Upload coverage to Codecov
        if: >-
          !cancelled()
          && !inputs.cpython-pip-version
        uses: codecov/codecov-action@v5
        with:
          files: ./coverage.xml
          flags: >-
            CI-GHA,
            OS-${{ runner.os }},
            VM-${{ matrix.os }},
            Py-${{ steps.python-install.outputs.python-version }},
            Pip-${{ matrix.pip-version }}
          name: >-
            OS-${{ runner.os }},
            VM-${{ matrix.os }},
            Py-${{ steps.python-install.outputs.python-version }},
            Pip-${{ matrix.pip-version }}

  pypy:
    name: ${{ matrix.os }} / ${{ matrix.python-version }} / ${{ matrix.pip-version }}
    runs-on: ${{ matrix.os }}-latest
    timeout-minutes: 9
    strategy:
      fail-fast: false
      matrix:
        os:
          - Ubuntu
          - MacOS
          - Windows
        python-version:
          - pypy-3.10
        pip-version:
          - supported
    env:
      TOXENV: pip${{ matrix.pip-version }}
    steps:
      - uses: actions/checkout@v5
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Get pip cache dir
        id: pip-cache
        shell: bash
        run: |
          echo "dir=$(pip cache dir)" >> "${GITHUB_OUTPUT}"
      - name: Pip cache
        uses: actions/cache@v4
        with:
          path: ${{ steps.pip-cache.outputs.dir }}
          key: >-
            ${{ runner.os }}-pip-${{ hashFiles('setup.cfg') }}-${{
            hashFiles('pyproject.toml') }}-${{ hashFiles('tox.ini') }}-${{
            hashFiles('.pre-commit-config.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pip-
            ${{ runner.os }}-
      - name: Install tox
        run: pip install tox
      - name: Prepare test environment
        # NOTE: `--parallel-live` is a workaround for the regression in
        # NOTE: the upstream tox project that made the
        # NOTE: `TOX_PARALLEL_NO_SPINNER=1` env var auto-enable parallelism
        # NOTE: and disable output from the tox environments.
        #
        # Ref: https://github.com/tox-dev/tox/issues/3193
        run: tox --notest -p auto --parallel-live
      - name: Test pip ${{ matrix.pip-version }}
        # NOTE: `--parallel-live` is a workaround for the regression in
        # NOTE: the upstream tox project that made the
        # NOTE: `TOX_PARALLEL_NO_SPINNER=1` env var auto-enable parallelism
        # NOTE: and disable output from the tox environments.
        #
        # Ref: https://github.com/tox-dev/tox/issues/3193
        run: tox --skip-pkg-install --parallel-live
      - name: Re-run the failing tests with maximum verbosity
        if: >-
          !cancelled()
          && failure()
        run: >-  # `exit 1` makes sure that the job remains red with flaky runs
          python -Xutf8 -Im
          tox
          --parallel=auto
          --parallel-live
          --skip-missing-interpreters=false
          --skip-pkg-install
          -vvvvv
          --
          --continue-on-collection-errors
          --full-trace
          --last-failed
          --numprocesses=0
          --showlocals
          --trace-config
          -rA
          -vvvvv
          && exit 1
        shell: bash

  coverage-summary:
    name: Coverage processing
    if: >-
      !cancelled()
    runs-on: ubuntu-latest
    timeout-minutes: 1
    needs:
      - test
    steps:
      - name: Notify Codecov that all coverage reports have been uploaded
        if: >-
          !cancelled()
        uses: codecov/codecov-action@v5
        with:
          fail_ci_if_error: true
          run_command: send-notifications

  zizmor:
    name: 🌈 zizmor
    permissions:
      security-events: write

    # yamllint disable-line rule:line-length
    uses: zizmorcore/workflow/.github/workflows/reusable-zizmor.yml@1e20adb0862e932363a4d85d68c92e5cc6fcb5d4

  check: # This job does nothing and is only used for the branch protection
    if: always()

    needs:
      - linters
      - pypy
      - test
      - zizmor

    runs-on: ubuntu-latest

    timeout-minutes: 1

    steps:
      - name: Decide whether the needed jobs succeeded or failed
        uses: re-actors/alls-green@afee1c1eac2a506084c274e9c02c8e0687b48d9e
        with:
          jobs: ${{ toJSON(needs) }}


================================================
FILE: .github/workflows/cron.yml
================================================
name: Cron

on:
  schedule:
    # Run everyday at 03:53 UTC
    - cron: 53 3 * * *

jobs:
  main:
    name: CI
    uses: ./.github/workflows/ci.yml
    with:
      cpython-versions: >-
        ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"]
      cpython-pip-version: >-
        ["main", "latest", "supported", "lowest"]


================================================
FILE: .github/workflows/release.yml
================================================
---
name: 📦 Packaging

on:
  release:
    types:
      - published

env:
  FORCE_COLOR: 1 # Request colored output from CLI tools supporting it
  MYPY_FORCE_COLOR: 1 # MyPy's color enforcement
  PIP_DISABLE_PIP_VERSION_CHECK: 1 # Hide "there's a newer pip" message
  PIP_NO_PYTHON_VERSION_WARNING: 1 # Hide "this Python is deprecated" message
  PIP_NO_WARN_SCRIPT_LOCATION: 1 # Hide "script dir is not in $PATH" message
  PRE_COMMIT_COLOR: always
  PY_COLORS: 1 # Recognized by the `py` package, dependency of `pytest`
  PYTHONIOENCODING: utf-8
  PYTHONUTF8: 1
  TOX_PARALLEL_NO_SPINNER: 1 # Disable tox's parallel run spinner animation
  TOX_TESTENV_PASSENV: >- # Make tox-wrapped tools see color requests
    FORCE_COLOR
    MYPY_FORCE_COLOR
    NO_COLOR
    PIP_DISABLE_PIP_VERSION_CHECK
    PIP_NO_PYTHON_VERSION_WARNING
    PIP_NO_WARN_SCRIPT_LOCATION
    PRE_COMMIT_COLOR
    PY_COLORS
    PYTEST_THEME
    PYTEST_THEME_MODE
    PYTHONIOENCODING
    PYTHONLEGACYWINDOWSSTDIO
    PYTHONUTF8

run-name: >-
  ${{
    github.event.action == 'published'
    && format('📦 Releasing {0}...', github.ref_name)
    || format('🌱 Smoke-testing packaging for commit {0}', github.sha)
  }}
  triggered by: ${{ github.event_name }} of ${{
    github.ref
  }} ${{
    github.ref_type
  }}
  (workflow run ID: ${{
    github.run_id
  }}; number: ${{
    github.run_number
  }}; attempt: ${{
    github.run_attempt
  }})

jobs:
  build-and-test:
    name: >-
      📦 ${{ github.ref_name }}
      [mode: ${{
        github.event.action == 'published'
        && 'release' || 'nightly'
      }}]
    uses: ./.github/workflows/ci.yml
    with:
      release-version: ${{ github.ref_name }}
      release-committish: ''

  publish-pypi:
    name: >-
      📦
      Publish v${{
        needs.build-and-test.outputs.project-version
      }} to PyPI
    needs:
      - build-and-test
    if: >-
      github.event.action == 'published'
      && fromJSON(needs.build-and-test.outputs.is-upstream-repository)

    runs-on: ubuntu-latest

    timeout-minutes: 2 # docker+network are slow sometimes

    environment:
      name: pypi
      url: >-
        https://pypi.org/project/${{
          needs.build-and-test.outputs.project-name
        }}/${{
          needs.build-and-test.outputs.project-version
        }}

    permissions:
      id-token: write # PyPI Trusted Publishing (OIDC)

    steps:
      - name: Download all the dists
        uses: actions/download-artifact@v4
        with:
          name: >-
            ${{ needs.build-and-test.outputs.dists-artifact-name }}
          path: dist/
      - name: >-
          📦
          Publish v${{
            needs.build-and-test.outputs.project-version
          }} to PyPI
          🔏
        uses: pypa/gh-action-pypi-publish@release/v1
      - name: Clean up the publish attestation leftovers
        run: rm -fv dist/*.publish.attestation
      - name: Upload packages to Jazzband
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          user: jazzband
          password: ${{ secrets.JAZZBAND_RELEASE_KEY }}
          repository-url: >-
            https://jazzband.co/projects/${{
              needs.build-and-test.outputs.project-name
            }}/upload


================================================
FILE: .github/workflows/reusable-qa.yml
================================================
name: QA

on:
  workflow_call:

jobs:
  qa:
    name: ${{ matrix.toxenv }}
    runs-on: ubuntu-latest
    timeout-minutes: 2  # network is slow sometimes
    strategy:
      fail-fast: false
      matrix:
        toxenv:
          - readme
          - build-docs
          - linkcheck-docs
          - changelog-draft
        python-version:
          - "3.13"
    env:
      PY_COLORS: 1
      TOXENV: ${{ matrix.toxenv }}
      TOX_PARALLEL_NO_SPINNER: 1
    steps:
      - uses: actions/checkout@v5
      - name: Set up Python ${{ matrix.python-version }}
        uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Get pip cache dir
        id: pip-cache
        run: |
          echo "dir=$(pip cache dir)" >> "${GITHUB_OUTPUT}"
      - name: Pip cache
        uses: actions/cache@v4
        with:
          path: ${{ steps.pip-cache.outputs.dir }}
          key: >-
            ${{ runner.os }}-pip-${{ hashFiles('setup.cfg') }}-${{
            hashFiles('pyproject.toml') }}-${{ hashFiles('tox.ini') }}-${{
            hashFiles('.pre-commit-config.yaml') }}
          restore-keys: |
            ${{ runner.os }}-pip-
            ${{ runner.os }}-
      - name: Prepare cache key
        id: cache-key
        run: echo "sha-256=$(python -VV | sha256sum | cut -d' ' -f1)" >> "${GITHUB_OUTPUT}"
      - uses: actions/cache@v4
        with:
          path: ~/.cache/pre-commit
          key: pre-commit|${{ steps.cache-key.outputs.sha-256 }}|${{ hashFiles('.pre-commit-config.yaml') }}
      - name: Install tox
        run: pip install tox
      - name: Prepare test environment
        run: tox -vv --notest -p auto --parallel-live
      - name: Test ${{ matrix.toxenv }}
        run: tox --skip-pkg-install


================================================
FILE: .gitignore
================================================
# Ignore cram test output
*.t.err

# Python cruft
*.pyc

# Virtualenvs
.envrc
.direnv
.venv
venv/

# Testing
.pytest_cache/
.tox
htmlcov

# Build output
build
dist
*.egg-info
.coverage
.coverage.*
coverage.xml
.cache

# IDE
.idea

# Test files
requirements.in
requirements.txt
.eggs/


================================================
FILE: .pre-commit-config.yaml
================================================
repos:
  - repo: https://github.com/psf/black-pre-commit-mirror
    rev: 26.3.1
    hooks:
      - id: black
        args: [--target-version=py39]
  - repo: https://github.com/PyCQA/isort
    rev: 8.0.1
    hooks:
      - id: isort
  - repo: https://github.com/asottile/pyupgrade
    rev: v3.21.2
    hooks:
      - id: pyupgrade
        args: [--py39-plus]

  - repo: https://github.com/python-jsonschema/check-jsonschema.git
    rev: 0.37.0
    hooks:
      - id: check-github-actions
      - id: check-github-workflows
      - id: check-jsonschema
        alias: enforce-gha-timeouts
        name: Check GitHub Workflows set timeout-minutes
        args:
          - --builtin-schema
          - github-workflows-require-timeout
        files: ^\.github/workflows/[^/]+$
        types:
          - yaml
      - id: check-readthedocs

  - repo: https://github.com/PyCQA/flake8
    rev: 7.3.0
    hooks:
      - id: flake8
        additional_dependencies:
          - flake8-pytest-style == 2.2.0
          - flake8-typing-as-t == 1.1.0
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.19.1
    hooks:
      - id: mypy
        # Avoid error: Duplicate module named 'setup'
        # https://github.com/python/mypy/issues/4008
        # Keep exclude in sync with mypy own excludes
        exclude: ^tests/test_data/
        additional_dependencies:
          - click==8.0.1
          - pep517==0.10.0
          - toml==0.10.2
          - pip==20.3.4
          - build==1.0.0
          - pyproject_hooks==1.0.0
          - pytest==7.4.2
  - repo: https://github.com/PyCQA/bandit
    rev: 1.9.4
    hooks:
      - id: bandit
        args: [--ini, .bandit]
        exclude: ^tests/

  - repo: local
    hooks:
    - id: changelogs-md
      name: changelog filenames
      language: fail
      entry: >-
        Changelog files must be named
        ####.(
        highlights
        | bugfix
        | feature
        | deprecation
        | breaking
        | doc
        | packaging
        | contrib
        | misc
        | afterword
        )(.#)?(.md)?
      exclude: >-
        (?x)
        ^
          changelog.d/(
            \.gitignore
            |\.towncrier_template\.md\.jinja
            |\.draft_changelog_partial\.md
            |README\.md
            |(\d+|[0-9a-f]{8}|[0-9a-f]{7}|[0-9a-f]{40}|\+[^.]+)\.(
              highlights
              |bugfix
              |feature
              |deprecation
              |breaking
              |doc
              |packaging
              |contrib
              |misc
              |afterword
            )(\.\d+)?(\.md)?
          )
        $
      files: ^changelog\.d/
      types: []
      types_or:
      - file
      - symlink

  - repo: https://github.com/rhysd/actionlint.git
    rev: v1.7.11
    hooks:
      - id: actionlint
        additional_dependencies:
          # actionlint has a shellcheck integration which extracts shell scripts in `run:` steps from GitHub Actions
          # and checks these with shellcheck.
          # The integration only works if shellcheck is installed.
          - "github.com/wasilibs/go-shellcheck/cmd/shellcheck@v0.11.1"

  - repo: https://github.com/jackdewinter/pymarkdown.git
    rev: v0.9.36
    hooks:
    - id: pymarkdown
      alias: md-changelog
      name: PyMarkdown (published change log)
      args:
      # NOTE: `no-emphasis-as-heading` trips on dates under version
      # NOTE: titles. Wrapping the dates with `<time>`, OTOH, causes
      # NOTE: `no-inline-html`. `no-duplicate-heading` is caused by
      # NOTE: having the same change log categories under multiple
      # NOTE: versions. Finally, `blanks-around-headings` and
      # NOTE: `no-multiple-blanks` are caused by our towncrier template
      # NOTE: injecting an additional visual separator line at the end
      # NOTE: of each release — this behavior is desired.
      - --disable-rules=blanks-around-headings,no-duplicate-heading,no-emphasis-as-heading,no-multiple-blanks
      - scan
      files: ^CHANGELOG\.md$
    - id: pymarkdown
      alias: md-changelog-fragments
      name: PyMarkdown (change log fragments)
      args:
      # NOTE: Towncrier-processed change log fragments must not have
      # NOTE: headings but `first-line-heading` demands the opposite.
      - --disable-rules=first-line-heading
      - scan
      files: ^changelog\.d/(.*\..*|\.draft_changelog_partial)\.md$
    - id: pymarkdown
      alias: md-issue-pr-templates
      name: PyMarkdown (issue and pull request templates)
      args:
      # NOTE: GitHub issue templates are YAML document sequences. The
      # NOTE: first document is YAML and the second is markdown.
      # NOTE: The beginning cannot adhere to the `first-line-heading`
      # NOTE: requirement. The PR templates are pure Markdown but the
      # NOTE: structure does not need a global heading since this role
      # NOTE: is fulfilled by the PR title field.
      - --disable-rules=first-line-heading
      - scan
      files: ^\.github/(ISSUE_TEMPLATE/[^/]*|PULL_REQUEST_TEMPLATE)\.md$
    - id: pymarkdown
      alias: md-generic
      name: PyMarkdown (remaining)
      exclude: >-
        (?x)
        ^
          (
            \.github/(ISSUE_TEMPLATE/[^/]*|PULL_REQUEST_TEMPLATE)\.md
            |changelog\.d/(
              \.draft_changelog_partial\.md
              |(\d+|[0-9a-f]{8}|[0-9a-f]{7}|[0-9a-f]{40}|\+[^.]+)\.(
                highlights
                |bugfix
                |feature
                |deprecation
                |breaking
                |doc
                |packaging
                |contrib
                |misc
                |afterword
              )(\.\d+)?(\.md)?
            )
            |CHANGELOG\.md
          )
        $

...


================================================
FILE: .pre-commit-hooks.yaml
================================================
- id: pip-compile
  name: pip-compile
  description: Automatically compile requirements.
  entry: pip-compile
  language: python
  files: ^requirements\.(in|txt)$
  pass_filenames: false


================================================
FILE: .pymarkdown.yml
================================================
---

{}

...


================================================
FILE: .readthedocs.yaml
================================================
# https://docs.readthedocs.io/en/stable/config-file/v2.html

version: 2

build:
  os: ubuntu-24.04

  # in order to have RTD use our tox configuration for the build, we take full
  # control over 'build.commands'
  # see also: https://github.com/astral-sh/uv/issues/10074#issuecomment-3128225815
  commands:
    # install/setup uv
    - asdf plugin add uv
    - asdf install uv latest
    - asdf global uv latest
    # use uv to get
    # - Python 3.13
    # - tox (with tox-uv)
    - uv tool install tox --with tox-uv --python "3.13" --managed-python
    # create the tox environment (`--notest` skips commands)
    - uv tool run tox run -e build-docs --notest -vvvvv
    # do the actual build step, to the RTD documented output directory
    - uv tool run tox run -e build-docs --skip-pkg-install -q -- "${READTHEDOCS_OUTPUT}"/html -b dirhtml


================================================
FILE: CHANGELOG.md
================================================
# Change log

<!-- towncrier release notes start -->

## v7.5.3

*2026-02-09*

### Bug fixes

- The option `--unsafe-package` is now normalized -- by {user}`shifqu`.

  *PRs and issues:* {issue}`2150`

- Fixed a bug in which `pip-compile` lost any index URL options when
  looking up hashes -- by {user}`sirosen`.

  This caused errors when a package was only available from an extra
  index, and caused `pip-compile` to incorrectly drop index URL options
  from output, even when they were present in the input requirements.

  *PRs and issues:* {issue}`2220`, {issue}`2294`, {issue}`2305`

- Fixed removal of temporary files used when reading requirements from stdin
  -- by {user}`sirosen`.

### Features

- `pip-tools` is now tested against Python 3.14 and 3.14t in CI, and
  marks them as supported in the core packaging metadata
  -- by {user}`webknjaz`.

  *PRs and issues:* {issue}`2255`

- pip-tools is now compatible with pip 26.0 -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2319`, {issue}`2320`

### Removals and backward incompatible breaking changes

- Removed support for Python 3.8 -- by {user}`sirosen`.

### Improved documentation

- The change log management infra now allows the maintainers to add notes
  before and after the regular categories -- by {user}`webknjaz`.

  *PRs and issues:* {issue}`2287`, {issue}`2322`

- Added documentation clarifying that `pip-compile` reads the existing
  output file as a constraint source, and how to use `--upgrade` to
  refresh dependencies -- by {user}`maliktafheem`.

  *PRs and issues:* {issue}`2307`

### Packaging updates and notes for downstreams

- `pip-tools` is now tested against Python 3.14 and 3.14t in CI, and
  marks them as supported in the core packaging metadata
  -- by {user}`webknjaz`.

  *PRs and issues:* {issue}`2255`

### Contributor-facing changes

- Consistency of the Markdown files is now being enforced by linting
  with {pypi}`pymarkdownlnt` -- by {user}`webknjaz`.

  *PRs and issues:* {issue}`2256`

- The linting is now set up to perform structured GitHub Actions
  workflows and actions checks against json schemas
  -- by {user}`webknjaz`.

  *PRs and issues:* {issue}`2273`

- The CI/CD is now set up so that the distribution build job
  is a part of the test pipeline. That pipeline is included in
  the release workflow which sources the artifact in produces.
  The tests must now pass for the release to be published to PyPI.

  -- by {user}`webknjaz`

  *PRs and issues:* {issue}`2274`

- Fix `actionlint` hook usage to always include `shellcheck` integration -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2281`

- Utilities for interacting with `pip` have started to move into the
  :py:mod:`piptools._internal._pip_api` subpackage -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2285`

- The change log management infra now allows the maintainers to add notes
  before and after the regular categories -- by {user}`webknjaz`.

  *PRs and issues:* {issue}`2287`, {issue}`2322`

- The linting is now set up to demand that {py:mod}`typing` is always
  imported as a module under the name of `_t` -- by {user}`webknjaz`.

  This is enforced by {user}`sirosen`'s {pypi}`flake8-typing-as-t`
  plugin for {pypi}`flake8`.

  *PRs and issues:* {issue}`2289`

- The {file}`tox.ini` and {file}`.github/` parts of the repository now
  have project leads assigned as GitHub code owners -- by {user}`webknjaz`.

  *PRs and issues:* {issue}`2291`

- Remove a redundant 'v' prefix from the CI release workflow job name -- by {user}`anandvenugopal-tech`.

  *PRs and issues:* {issue}`2300`

- The `check-jsonschema` ReadTheDocs hook has been enabled, and
  the config has been tweaked to pass -- by {user}`sirosen`.


## v7.5.2

*2025-11-11*

### Bug fixes

- Fixed `pip-compile` to handle relative path includes which are not subpaths of
  the current working directory -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2231`, {issue}`2260`

- Using `--upgrade-package` and dynamically building project metadata no
  longer causes an {exc}`AttributeError` when pip encounters an error during the
  build -- by {user}`Epic_Wink` and {user}`tusharsadhwani`.

  *PRs and issues:* {issue}`2258`

### Features

- Test and declare Python 3.13 support -- by {user}`jayaddison` (for OpenCulinary).

  *PRs and issues:* {issue}`2251`

- pip-tools is now compatible with pip 25.3 -- by {user}`shifqu`.

  *PRs and issues:* {issue}`2252`, {issue}`2253`

### Packaging updates and notes for downstreams

- `pip-tools` now supports installation from git archives by providing
  `setuptools-scm` with `.git_archival.txt` data.

  *PRs and issues:* {issue}`2225`

### Contributor-facing changes

- The [change log entry bot] has been explicitly configured to stop requiring
  news fragments in pull requests having the [`bot:chronographer:skip` label] set
  -- by {user}`sirosen` and {user}`webknjaz`.

  It was also set up to reference our change log authoring document from the
  GitHub Checks pages. And the reported check name is now set to `Change log entry`.

  [change log entry bot]: https://github.com/sanitizers/chronographer-github-app
  [`bot:chronographer:skip` label]: https://github.com/jazzband/pip-tools/labels/bot:chronographer:skip

  *PRs and issues:* {issue}`2201`

- The CI is now set up to invoke failed tests again with
  maximum level of detail -- by {user}`webknjaz`.

  The change is aimed at helping troubleshoot failures
  that might be difficult to reproduce locally.

  *PRs and issues:* {issue}`2254`

- The integration with Codecov has been updated to ensure that reports
  are uploaded to the service even on failures -- by {user}`webknjaz`.

  GitHub Actions is now configured to also send an explicit notification
  to Codecov about the completion of previously initiated uploads.

  Additionally, the configuration file is now {file}`.codecov.yml`.

  *PRs and issues:* {issue}`2265`

- The linting suite now runs [`actionlint`] -- by {user}`webknjaz`.

  This tool checks typical problems with GitHub Actions workflow
  definitions and has a registry of widely-used GitHub Action
  arguments that it validates.

  [`actionlint`]: https://rhysd.github.io/actionlint/

  *PRs and issues:* {issue}`2266`


## v7.5.1

*2025-09-26*

### Bug fixes

- Fixed static parsing of {file}`pyproject.toml` data when the
  {file}`pyproject.toml` is supplied as a relative path -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2215`, {issue}`2221`, {issue}`2233`

- The "via" paths in `pip-compile` output for requirements discovered from
  `pyproject.toml` data are now written in POSIX format -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2221`

- Fixed a bug which removed slashes from URLs in ``-r`` and ``-c`` in the output
  of ``pip-compile`` -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2223`

- Fixed an incompatibility with ``click >= 8.3`` which made ``pip-compile``
  display incorrect options in the compile command in output headers
  -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2235`

### Features

- `pip-tools` now officially supports `pip` version 25.2 -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2214`

### Improved documentation

- ReadTheDocs builds for `pip-tools` no longer include htmlzip and pdf outputs
  -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2218`

### Contributor-facing changes

- `pip-tools` now tests on `pip` version 25.2 -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2214`

- The changelog documentation for contributors now provides hyperlinks to the
  source of each example change note -- by {user}`jayaddison`
  (for OpenCulinary).

  *PRs and issues:* {issue}`2217`

- The CPython versions tested in nightly CI runs are now separate from
  branch and PR CI, and don't include very old versions -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2226`


## v7.5.0

*2025-07-30*

### Bug fixes

- Fixed the ordering of format controls to preserve underlying `pip` behavior
  -- by {user}`sethmlarson`.

  *PRs and issues:* {issue}`2082`

- Fixed `NoCandidateFound` exception to be compatible with `pip >= 24.1`
  -- by {user}`chrysle`.

  *PRs and issues:* {issue}`2083`

- `pip-compile` now produces relative paths for editable dependencies
  -- by {user}`macro1`.

  *PRs and issues:* {issue}`2087`

- Fixed crash failures due to incompatibility with `pip >= 25.1`
  -- by {user}`gkreitz` and {user}`sirosen`.

  *PRs and issues:* {issue}`2176`, {issue}`2178`

### Features

- `pip-compile` now treats package versions requested on the command line as
  constraints for the underlying `pip` usage.
  This applies to build deps in addition to normal package requirements.

  -- by {user}`chrysle`

  *PRs and issues:* {issue}`2106`

- `pip-tools` now tests on and officially supports Python 3.12
  -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2188`

- Requirements file paths in `pip-compile` output are now normalized to
  POSIX-style, even when `pip-compile` is run on Windows.
  This provides more consistent output across various platforms.

  -- by {user}`sirosen`

  *PRs and issues:* {issue}`2195`

- `pip-tools` now tests against and supports `pip` up to version `25.1`
  -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2195`

### Removals and backward incompatible breaking changes

- `pip-compile` will now relativize the requirements paths which are recorded in
  its output.
  Paths are made relative to the working directory.
  This provides more consistent results across `pip` versions.

  -- by {user}`sirosen`

  *PRs and issues:* {issue}`2131`, {issue}`2195`

### Packaging updates and notes for downstreams

- `pip-tools` releases are now configured via Trusted Publishing.
  This allows for signature and attestation verification via PyPI.

  -- by {user}`webknjaz`

  *PRs and issues:* {issue}`2149`, {issue}`2209`, {issue}`2210`

### Contributor-facing changes

- `pip-tools`'s CI now runs against pinned `pip` versions, declared in `tox`
  configuration as the "supported" version.
  This does not change the support policy for `pip` versions, but declares what
  is tested and known to work.

  -- by {user}`webknjaz`

  *PRs and issues:* {issue}`2142`

- `pip-tools` now tests against PyPy 3.10 as its supported PyPy version
  -- by {user}`webknjaz`.

  *PRs and issues:* {issue}`2146`

- `pip-tools` now uses Towncrier to manage the changelog
  -- by {user}`sirosen` and {user}`webknjaz`,
  with suggestions from {user}`jayaddison`.

  *PRs and issues:* {issue}`2201`, {issue}`2203`

- `pip-tools` now uses [`sphinx-issues`](https://github.com/sloria/sphinx-issues)
  to link to issues, PRs, commits, and user accounts
  -- by {user}`sirosen`.

  *PRs and issues:* {issue}`2202`

## v7.4.1

*05 Mar 2024*

### Bug Fixes

- Skip constraint path check ({pr}`2038`)
  -- by {user}`honnix`.
- Fix collecting deps for all extras in multiple input packages ({pr}`1981`)
  -- by {user}`dragly`.

## v7.4.0

*16 Feb 2024*

### Features

- Allow force-enabling or force-disabling colorized output ({pr}`2041`)
  -- by {user}`aneeshusa`.
- Add support for command-specific configuration sections ({pr}`1966`)
  -- by {user}`chrysle`.
- Add options for including build dependencies in compiled output ({pr}`1681`)
  -- by {user}`apljungquist`.

### Bug Fixes

- Fix for `src-files` not being used when specified in a config file ({pr}`2015`)
  -- by {user}`csalerno-asml`.
- Fix ignorance of inverted CLI options in config for `pip-sync` ({pr}`1989`)
  -- by {user}`chrysle`.
- Filter out origin ireqs for extra requirements before writing output
  annotations ({pr}`2011`) -- by {user}`chrysle`.
- Make BacktrackingResolver ignore extras when dropping existing constraints ({pr}`1984`)
  -- by {user}`chludwig-haufe`.
- Display `pyproject.toml`'s metatada parsing errors in verbose mode ({pr}`1979`)
  -- by {user}`szobov`.

### Other Changes

- Add mention of pip-compile-multi in Other useful tools README section ({pr}`1986`)
  -- by {user}`peterdemin`.

## v7.3.0

*09 Aug 2023*

### Features

- Add `--no-strip-extras` and warn about strip extras by default ({pr}`1954`)
  -- by {user}`ryanhiebert`.

### Bug Fixes

- Fix revealed default config in header if requirements in subfolder ({pr}`1904`)
  -- by {user}`atugushev`.
- Direct references show extra requirements in .txt files ({pr}`1582`)
  -- by {user}`FlorentJeannot`.

### Other Changes

- Document how to run under `pipx run` ({pr}`1951`)
  -- by {user}`brettcannon`.
- Document that the backtracking resolver is the current default ({pr}`1948`)
  -- by {user}`jeffwidman`.

## v7.2.0

*02 Aug 2023*

### Features

- Add `-c/--constraint` option to `pip-compile` ({pr}`1936`)
  -- by {user}`atugushev`.

### Bug Fixes

- Allow options in config from both `pip-compile` and `pip-sync` ({pr}`1933`)
  -- by {user}`atugushev`.
- Fix rejection of negating CLI boolean flags in config ({pr}`1913`)
  -- by {user}`chrysle`.

### Other Changes

- Add Command Line Reference section to docs ({pr}`1934`)
  -- by {user}`atugushev`.

## v7.1.0

*18 Jul 2023*

### Features

- Validate parsed config against CLI options ({pr}`1910`)
  -- by {user}`atugushev`.

### Bug Fixes

- Fix a bug where `pip-sync` would unexpectedly uninstall some packages ({pr}`1919`)
  -- by {user}`atugushev`.

## v7.0.0

*14 Jul 2023*

### Backwards Incompatible Changes

- Default to `--resolver=backtracking` ({pr}`1897`)
  -- by {user}`atugushev`.
- Drop support for Python 3.7 ({pr}`1879`)
  -- by {user}`chrysle`.

### Features

- Add support for `pip==23.2` where refactored out `DEV_PKGS` ({pr}`1906`)
  -- by {user}`atugushev`.
- Add `--no-config` option ({pr}`1896`)
  -- by {user}`atugushev`.

### Bug Fixes

- Sync direct references with hashes ({pr}`1885`)
  -- by {user}`siddharthab`.
- Fix missing `via`s when more than two input files are used ({pr}`1890`)
  -- by {user}`lpulley`.

## v6.14.0

*28 Jun 2023*

### Features

- Support config defaults using `.pip-tools.toml` or `pyproject.toml` ({pr}`1863`)
  -- by {user}`j00bar`.
- Log a warning if the user specifies `-P` and the output file is present but
  empty ({pr}`1822`) -- by {user}`davidmreed`.
- Improve warning for `pip-compile` if no `--allow-unsafe` was passed ({pr}`1867`)
  -- by {user}`chrysle`.

### Other Changes

- Correct in README `pre-commit` hook to run off `requirements.in` ({pr}`1847`)
  -- by {user}`atugushev`.
- Add pyprojects.toml example for using setuptools ({pr}`1851`)
  -- by {user}`shatakshiiii`.

## v6.13.0

*07 Apr 2023*

### Features

- Add support for self-referential extras ({pr}`1791`)
  -- by {user}`q0w`.
- Add support for `pip==23.1` where removed `FormatControl` in `WheelCache` ({pr}`1834`)
  -- by {user}`atugushev`.
- Add support for `pip==23.1` where refactored requirement options ({pr}`1832`)
  -- by {user}`atugushev`.
- Add support for `pip==23.1` where deprecated `--install-option` has been
  removed ({pr}`1828`) -- by {user}`atugushev`.

### Bug Fixes

- Pass `--cache-dir` to `--pip-args` for backtracking resolver ({pr}`1827`)
  -- by {user}`q0w`.

### Other Changes

- Update examples in README ({pr}`1835`)
  -- by {user}`lucaswerkmeister`.

## v6.12.3

*01 Mar 2023*

### Bug Fixes

- Remove extras from user-supplied constraints in backtracking resolver ({pr}`1808`)
  -- by {user}`thomdixon`.
- Fix for sync error when the ireqs being merged have no names ({pr}`1802`)
  -- by {user}`richafrank`.

## v6.12.2

*25 Dec 2022*

### Bug Fixes

- Raise error if input and output filenames are matched ({pr}`1787`)
  -- by {user}`atugushev`.
- Add `pyproject.toml` as default input file format ({pr}`1780`)
  -- by {user}`berislavlopac`.
- Fix a regression with unsafe packages for `--allow-unsafe` ({pr}`1788`)
  -- by {user}`q0w`.

## v6.12.1

*16 Dec 2022*

### Bug Fixes

- Set explicitly packages for setuptools ({pr}`1782`)
  -- by {user}`q0w`.

## v6.12.0

*13 Dec 2022*

### Features

- Add `--no-index` flag to `pip-compile` ({pr}`1745`)
  -- by {user}`atugushev`.

### Bug Fixes

- Treat `--upgrade-packages` PKGSPECs as constraints (not just minimums),
  consistently ({pr}`1578`) -- by {user}`AndydeCleyre`.
- Filter out the user provided unsafe packages ({pr}`1766`)
  -- by {user}`q0w`.
- Adopt PEP-621 for packaging ({pr}`1763`)
  -- by {user}`ssbarnea`.

## v6.11.0

*30 Nov 2022*

### Features

- Add `pyproject.toml` file ({pr}`1643`)
  -- by {user}`otherJL0`.
- Support build isolation using `setuptools/pyproject.toml` requirement files ({pr}`1727`)
  -- by {user}`atugushev`.

### Bug Fixes

- Improve punctuation/grammar with `pip-compile` header ({pr}`1547`)
  -- by {user}`blueyed`.
- Generate hashes for all available candidates ({pr}`1723`)
  -- by {user}`neykov`.

### Other Changes

- Bump click minimum version to `>= 8` ({pr}`1733`)
  -- by {user}`atugushev`.
- Bump pip minimum version to `>= 22.2` ({pr}`1729`)
  -- by {user}`atugushev`.

## v6.10.0

*13 Nov 2022*

### Features

- Deprecate `pip-compile --resolver=legacy` ({pr}`1724`)
  -- by {user}`atugushev`.
- Prompt user to use the backtracking resolver on errors ({pr}`1719`)
  -- by {user}`maxfenv`.
- Add support for Python 3.11 final ({pr}`1708`)
  -- by {user}`hugovk`.
- Add `--newline=[LF|CRLF|native|preserve]` option to `pip-compile` ({pr}`1652`)
  -- by {user}`AndydeCleyre`.

### Bug Fixes

- Fix inconsistent handling of constraints comments with backtracking resolver ({pr}`1713`)
  -- by {user}`mkniewallner`.
- Fix some encoding warnings in Python 3.10 (PEP 597) ({pr}`1614`)
  -- by {user}`GalaxySnail`.

### Other Changes

- Update pip-tools version in the README's pre-commit examples ({pr}`1701`)
  -- by {user}`Kludex`.
- Document use of the backtracking resolver ({pr}`1718`)
  -- by {user}`maxfenv`.
- Use HTTPS in a readme link ({pr}`1716`)
  -- by {user}`Arhell`.

## v6.9.0

*05 Oct 2022*

### Features

- Add `--all-extras` flag to `pip-compile` ({pr}`1630`)
  -- by {user}`apljungquist`.
- Support Exclude Package with custom unsafe packages ({pr}`1509`)
  -- by {user}`hmc-cs-mdrissi`.

### Bug Fixes

- Fix compile cached vcs packages ({pr}`1649`)
  -- by {user}`atugushev`.
- Include `py.typed` in wheel file ({pr}`1648`)
  -- by {user}`FlorentJeannot`.

### Other Changes

- Add pyproject.toml & modern packaging to introduction ({pr}`1668`)
  -- by {user}`hynek`.

## v6.8.0

*30 Jun 2022*

### Features

- Add support for pip's 2020 dependency resolver. Use
  `pip-compile --resolver backtracking` to enable new resolver ({pr}`1539`)
  -- by {user}`atugushev`.

## v6.7.0

*27 Jun 2022*

### Features

- Support for the `importlib.metadata` metadata implementation ({pr}`1632`)
  -- by {user}`richafrank`.

### Bug Fixes

- Instantiate a new accumulator `InstallRequirement` for `combine_install_requirements`
  output ({pr}`1519`)
  -- by {user}`richafrank`.

### Other Changes

- Replace direct usage of the `pep517` module with the `build` module, for loading
  project metadata ({pr}`1629`)
  -- by {user}`AndydeCleyre`.

## v6.6.2

*23 May 2022*

### Bug Fixes

- Update `PyPIRepository::resolve_reqs()` for pip>=22.1.1 ({pr}`1624`)
  -- by {user}`m000`.

## v6.6.1

*13 May 2022*

### Bug Fixes

- Fix support for pip>=22.1 ({pr}`1618`)
  -- by {user}`wizpig64`.

## v6.6.0

*06 Apr 2022*

### Features

- Add support for pip>=22.1 ({pr}`1607`)
  -- by {user}`atugushev`.

### Bug Fixes

- Ensure `pip-compile --dry-run --quiet` still shows what would be done, while omitting
  the dry run message ({pr}`1592`)
  -- by {user}`AndydeCleyre`.
- Fix `--generate-hashes` when hashes are computed from files ({pr}`1540`)
  -- by {user}`RazerM`.

## v6.5.1

*08 Feb 2022*

### Bug Fixes

- Ensure canonicalized requirement names are used as keys, to prevent unnecessary
  reinstallations during sync ({pr}`1572`)
  -- by {user}`AndydeCleyre`.

## v6.5.0

*04 Feb 2022*

### Features

- Add support for pip>=22.0, drop support for Python 3.6 ({pr}`1567`)
  -- by {user}`di`.
- Test on Python 3.11 ({pr}`1527`)
  -- by {user}`hugovk`.

### Other Changes

- Minor doc edits ({pr}`1445`)
  -- by {user}`ssiano`.

## v6.4.0

*12 Oct 2021*

### Features

- Add support for `pip>=21.3` ({pr}`1501`)
  -- by {user}`atugushev`.
- Add support for Python 3.10 ({pr}`1497`)
  -- by {user}`joshuadavidthomas`.

### Other Changes

- Bump pip minimum version to `>= 21.2` ({pr}`1500`)
  -- by {user}`atugushev`.

## v6.3.1

*08 Oct 2021*

### Bug Fixes

- Ensure `pip-tools` unions dependencies of multiple declarations of a package with
  different extras ({pr}`1486`)
  -- by {user}`richafrank`.
- Allow comma-separated arguments for `--extra` ({pr}`1493`)
  -- by {user}`AndydeCleyre`.
- Improve clarity of help text for options supporting multiple ({pr}`1492`)
  -- by {user}`AndydeCleyre`.

## v6.3.0

*21 Sep 2021*

### Features

- Enable single-line annotations with `pip-compile --annotation-style=line` ({pr}`1477`)
  -- by {user}`AndydeCleyre`.
- Generate PEP 440 direct reference whenever possible ({pr}`1455`)
  -- by {user}`FlorentJeannot`.
- PEP 440 Direct Reference support ({pr}`1392`)
  -- by {user}`FlorentJeannot`.

### Bug Fixes

- Change log level of hash message ({pr}`1460`)
  -- by {user}`plannigan`.
- Allow passing `--no-upgrade` option ({pr}`1438`)
  -- by {user}`ssbarnea`.

## v6.2.0

*22 Jun 2021*

### Features

- Add `--emit-options/--no-emit-options` flags to `pip-compile` ({pr}`1123`)
  -- by {user}`atugushev`.
- Add `--python-executable` option for `pip-sync` ({pr}`1333`)
  -- by {user}`MaratFM`.
- Log which python version was used during compile ({pr}`828`)
  -- by {user}`graingert`.

### Bug Fixes

- Fix `pip-compile` package ordering ({pr}`1419`)
  -- by {user}`adamsol`.
- Add `--strip-extras` option to `pip-compile` for producing constraint compatible
  output ({pr}`1404`)
  -- by {user}`ssbarnea`.
- Fix `click` v7 `version_option` compatibility ({pr}`1410`)
  -- by {user}`FuegoFro`.
- Pass `package_name` explicitly in `click.version_option` decorators for compatibility
  with `click>=8.0` ({pr}`1400`)
  -- by {user}`nicoa`.

### Other Changes

- Document updating requirements with `pre-commit` hooks ({pr}`1387`)
  -- by {user}`microcat49`.
- Add `setuptools` and `wheel` dependencies to the `setup.cfg` ({pr}`889`)
  -- by {user}`jayvdb`.
- Improve instructions for new contributors ({pr}`1394`)
  -- by {user}`FlorentJeannot`.
- Better explain role of existing `requirements.txt` ({pr}`1369`)
  -- by {user}`mikepqr`.

## v6.1.0

*14 Apr 2021*

### Features

- Add support for `pyproject.toml` or `setup.cfg` as input dependency file
  {pep}`517` for `pip-compile` ({pr}`1356`)
  -- by {user}`orsinium`.
- Add `pip-compile --extra` option to specify `extras_require` dependencies
  ({pr}`1363`) -- by {user}`orsinium`.

### Bug Fixes

- Restore ability to set compile cache with env var `PIP_TOOLS_CACHE_DIR` ({pr}`1368`)
  -- by {user}`AndydeCleyre`.

## v6.0.1

*15 Mar 2021*

### Bug Fixes

- Fixed a bug with undeclared dependency on `importlib-metadata` at Python 3.6 ({pr}`1353`)
  -- by {user}`atugushev`.

### Dependencies

- Add `pep517` dependency ({pr}`1353`)
  -- by {user}`atugushev`.

## v6.0.0

*12 Mar 2021*

### Backwards Incompatible Changes

- Remove support for EOL Python 3.5 and 2.7 ({pr}`1243`)
  -- by {user}`jdufresne`.
- Remove deprecated `--index/--no-index` option from `pip-compile` ({pr}`1234`)
  -- by {user}`jdufresne`.

### Features

- Use `pep517` to parse dependencies metadata from `setup.py` ({pr}`1311`)
  -- by {user}`astrojuanlu`.

### Bug Fixes

- Fix a bug where `pip-compile` with `setup.py` would not include dependencies with
  environment markers ({pr}`1311`)
  -- by {user}`astrojuanlu`.
- Prefer `===` over `==` when generating `requirements.txt` if a dependency was pinned
  with `===` ({pr}`1323`)
  -- by {user}`IceTDrinker`.
- Fix a bug where `pip-compile` with `setup.py` in nested folder would generate
  `setup.txt` output file ({pr}`1324`)
  -- by {user}`peymanslh`.
- Write out default index when it is provided as `--extra-index-url` ({pr}`1325`)
  -- by {user}`fahrradflucht`.

### Dependencies

- Bump `pip` minimum version to `>= 20.3` ({pr}`1340`)
  -- by {user}`atugushev`.

## v5.5.0

*31 Dec 2020*

### Features

- Add Python 3.9 support ({pr}`1222`)
  -- by {user}`jdufresne`.
- Improve formatting of long "via" annotations ({pr}`1237`)
  -- by {user}`jdufresne`.
- Add `--verbose` and `--quiet` options to `pip-sync` ({pr}`1241`)
  -- by {user}`jdufresne`.
- Add `--no-allow-unsafe` option to `pip-compile` ({pr}`1265`)
  -- by {user}`jdufresne`.

### Bug Fixes

- Restore `PIP_EXISTS_ACTION` environment variable to its previous state when resolve
  dependencies in `pip-compile` ({pr}`1255`)
  -- by {user}`jdufresne`.

### Dependencies

- Remove `six` dependency in favor `pip`'s vendored `six` ({pr}`1240`)
  -- by {user}`jdufresne`.

### Improved Documentation

- Add `pip-requirements.el` (for Emacs) to useful tools to `README` ({pr}`1244`)
  -- by {user}`jdufresne`.
- Add supported Python versions to `README` ({pr}`1246`)
  -- by {user}`jdufresne`.

## v5.4.0

*21 Nov 2020*

### Features

- Add `pip>=20.3` support ({pr}`1216`)
  -- by {user}`atugushev` and {user}`AndydeCleyre`.
- Exclude `--no-reuse-hashes` option from «command to run» header ({pr}`1197`)
  -- by {user}`graingert`.

### Dependencies

- Bump `pip` minimum version to `>= 20.1` ({pr}`1191`)
  -- by {user}`atugushev` and {user}`AndydeCleyre`.

## v5.3.1

*31 Jul 2020*

### Bug Fixes

- Fix `pip-20.2` compatibility issue that caused `pip-tools` to sometime fail to
  stabilize in a constant number of rounds ({pr}`1194`)
  -- by {user}`vphilippon`.

## v5.3.0

*26 Jul 2020*

### Features

- Add `-h` alias for `--help` option to `pip-sync` and `pip-compile` ({pr}`1163`)
  -- by {user}`jan25`.
- Add `pip>=20.2` support ({pr}`1168`)
  -- by {user}`atugushev`.
- `pip-sync` now exists with code `1` on `--dry-run` ({pr}`1172`)
  -- by {user}`francisbrito`.
- `pip-compile` now doesn't resolve constraints from `-c constraints.txt`that
  are not (yet) requirements ({pr}`1175`) -- by {user}`clslgrnc`.
- Add `--reuse-hashes/--no-reuse-hashes` options to `pip-compile` ({pr}`1177`)
  -- by {user}`graingert`.

## v5.2.1

*09 Jun 2020*

### Bug Fixes

- Fix a bug where `pip-compile` would lose some dependencies on update a
  `requirements.txt` ({pr}`1159`)
  -- by {user}`richafrank`.

## v5.2.0

*27 May 2020*

### Features

- Show basename of URLs when `pip-compile` generates hashes in a verbose mode ({pr}`1113`)
  -- by {user}`atugushev`.
- Add `--emit-index-url/--no-emit-index-url` options to `pip-compile` ({pr}`1130`)
  -- by {user}`atugushev`.

### Bug Fixes

- Fix a bug where `pip-compile` would ignore some of package versions when
  `PIP_PREFER_BINARY` is set on ({pr}`1119`)
  -- by {user}`atugushev`.
- Fix leaked URLs with credentials in the debug output of `pip-compile` ({pr}`1146`)
  -- by {user}`atugushev`.
- Fix a bug where URL requirements would have name collisions ({pr}`1149`)
  -- by {user}`geokala`.

### Deprecations

- Deprecate `--index/--no-index` in favor of `--emit-index-url/--no-emit-index-url`
  options in `pip-compile` ({pr}`1130`)
  -- by {user}`atugushev`.

### Other Changes

- Switch to `setuptools` declarative syntax through `setup.cfg` ({pr}`1141`)
  -- by {user}`jdufresne`.

## v5.1.2

*05 May 2020*

### Bug Fixes

- Fix grouping of editables and non-editables requirements ({pr}`1132`)
  -- by {user}`richafrank`.

## v5.1.1

*01 May 2020*

### Bug Fixes

- Fix a bug where `pip-compile` would generate hashes for `*.egg` files ({pr}`1122`)
  -- by {user}`atugushev`.

## v5.1.0

*27 Apr 2020*

### Features

- Show progress bar when downloading packages in `pip-compile` verbose mode ({pr}`949`)
  -- by {user}`atugushev`.
- `pip-compile` now gets hashes from `PyPI` JSON API (if available) which significantly
  increases the speed of hashes generation ({pr}`1109`)
  -- by {user}`atugushev`.

## v5.0.0

*16 Apr 2020*

### Backwards Incompatible Changes

- `pip-tools` now requires `pip>=20.0` (previously `8.1.x` - `20.0.x`). Windows users,
  make sure to use `python -m pip install pip-tools` to avoid issues with `pip`
  self-update from now on ({pr}`1055`)
  -- by {user}`atugushev`.
- `--build-isolation` option now set on by default for `pip-compile` ({pr}`1060`)
  -- by {user}`hramezani`.

### Features

- Exclude requirements with non-matching markers from `pip-sync` ({pr}`927`)
  -- by {user}`AndydeCleyre`.
- Add `pre-commit` hook for `pip-compile` ({pr}`976`)
  -- by {user}`atugushev`.
- `pip-compile` and `pip-sync` now pass anything provided to the new
  `--pip-args` option on to `pip` ({pr}`1080`) -- by {user}`AndydeCleyre`.
- `pip-compile` output headers are now more accurate when `--` is used to escape
  filenames ({pr}`1080`)
  -- by {user}`AndydeCleyre`.
- Add `pip>=20.1` support ({pr}`1088`)
  -- by {user}`atugushev`.

### Bug Fixes

- Fix a bug where editables that are both direct requirements and constraints wouldn't
  appear in `pip-compile` output ({pr}`1093`)
  -- by {user}`richafrank`.
- `pip-compile` now sorts format controls (`--no-binary/--only-binary`) to ensure
  consistent results ({pr}`1098`)
  -- by {user}`richafrank`.

### Improved Documentation

- Add cross-environment usage documentation to `README` ({pr}`651`)
  -- by {user}`vphilippon`.
- Add versions compatibility table to `README` ({pr}`1106`)
  -- by {user}`atugushev`.

## v4.5.1

*26 Feb 2020*

### Bug Fixes

- Strip line number annotations such as "(line XX)" from file requirements, to prevent
  diff noise when modifying input requirement files ({pr}`1075`)
  -- by {user}`adamchainz`.

### Improved Documentation

- Updated `README` example outputs for primary requirement annotations ({pr}`1072`)
  -- by {user}`richafrank`.

## v4.5.0

*20 Feb 2020*

### Features

- Primary requirements and VCS dependencies are now get annotated with any
  source `.in` files and reverse dependencies ({pr}`1058`)
  -- by {user}`AndydeCleyre`.

### Bug Fixes

- Always use normalized path for cache directory as it is required in newer
  versions of `pip` ({pr}`1062`) -- by {user}`kammala`.

### Improved Documentation

- Replace outdated link in the `README` with rationale for pinning ({pr}`1053`)
  -- by {user}`m-aciek`.

## v4.4.1

*31 Jan 2020*

### Bug Fixes

- Fix a bug where `pip-compile` would keep outdated options from
  `requirements.txt` ({pr}`1029`) -- by {user}`atugushev`.
- Fix the `No handlers could be found for logger "pip.*"` error by configuring the
  builtin logging module ({pr}`1035`)
  -- by {user}`vphilippon`.
- Fix a bug where dependencies of relevant constraints may be missing from
  output file ({pr}`1037`) -- by {user}`jeevb`.
- Upgrade the minimal version of `click` from `6.0` to `7.0` version in
  `setup.py` ({pr}`1039`) -- by {user}`hramezani`.
- Ensure that depcache considers the python implementation such that (for example)
  `cpython3.6` does not poison the results of `pypy3.6` ({pr}`1050`)
  -- by {user}`asottile`.

### Improved Documentation

- Make the `README` more imperative about installing into a project's virtual
  environment to avoid confusion ({pr}`1023`)
  -- by {user}`tekumara`.
- Add a note to the `README` about how to install requirements on different
  stages to
  [Workflow for layered requirements](https://pip-tools.rtfd.io/en/latest/#workflow-for-layered-requirements)
  section ({pr}`1044`)
  -- by {user}`hramezani`.

## v4.4.0

*21 Jan 2020*

### Features

- Add `--cache-dir` option to `pip-compile` ({pr}`1022`)
  -- by {user}`richafrank`.
- Add `pip>=20.0` support ({pr}`1024`)
  -- by {user}`atugushev`.

### Bug Fixes

- Fix a bug where `pip-compile --upgrade-package` would upgrade those passed packages
  not already required according to the `*.in` and `*.txt` files ({pr}`1031`)
  -- by {user}`AndydeCleyre`.

## v4.3.0

*25 Nov 2019*

### Features

- Add Python 3.8 support ({pr}`956`)
  -- by {user}`hramezani`.
- Unpin commented out unsafe packages in `requirements.txt` ({pr}`975`)
  -- by {user}`atugushev`.

### Bug Fixes

- Fix `pip-compile` doesn't copy `--trusted-host` from `requirements.in` to
  `requirements.txt` ({pr}`964`)
  -- by {user}`atugushev`.
- Add compatibility with `pip>=20.0`
  ({pr}`953` and
  {pr}`978`)
  -- by {user}`atugushev`.
- Fix a bug where the resolver wouldn't clean up the ephemeral wheel cache ({pr}`968`)
  -- by {user}`atugushev`.

### Improved Documentation

- Add a note to `README` about `requirements.txt` file, which would possibly interfere
  if you're compiling from scratch ({pr}`959`)
  -- by {user}`hramezani`.

## v4.2.0

*12 Oct 2019*

### Features

- Add `--ask` option to `pip-sync` ({pr}`913`)
  -- by {user}`georgek`.

### Bug Fixes

- Add compatibility with `pip>=19.3`
  ({pr}`864`,
  {pr}`904`,
  {pr}`910`,
  {pr}`912` and
  {pr}`915`)
  -- by {user}`atugushev`.
- Ensure `pip-compile --no-header <blank requirements.in>` creates/overwrites
  `requirements.txt` ({pr}`909`)
  -- by {user}`AndydeCleyre`.
- Fix `pip-compile --upgrade-package` removes «via» annotation ({pr}`931`)
  -- by {user}`hramezani`.

### Improved Documentation

- Add info to `README` about layered requirements files and `-c` flag ({pr}`905`)
  -- by {user}`jamescooke`.

## v4.1.0

*26 Aug 2019*

### Features

- Add `--no-emit-find-links` option to `pip-compile` ({pr}`873`)
  -- by {user}`jacobtolar`.

### Bug Fixes

- Prevent `--dry-run` log message from being printed with `--quiet` option in
  `pip-compile` ({pr}`861`)
  -- by {user}`ddormer`.
- Fix resolution of requirements from Git URLs without `-e` ({pr}`879`)
  -- by {user}`andersk`.

## v4.0.0

*25 Jul 2019*

### Backwards Incompatible Changes

- Drop support for EOL Python 3.4 ({pr}`803`)
  -- by {user}`auvipy`.

### Bug Fixes

- Fix `pip>=19.2` compatibility ({pr}`857`)
  -- by {user}`atugushev`.

## v3.9.0

*17 Jul 2019*

### Features

- Print provenance information when `pip-compile` fails ({pr}`837`)
  -- by {user}`jakevdp`.

### Bug Fixes

- Output all logging to stderr instead of stdout ({pr}`834`)
  -- by {user}`georgek`.
- Fix output file update with `--dry-run` option in `pip-compile` ({pr}`842`)
  -- by {user}`shipmints` and.
  {user}`atugushev`

## v3.8.0

*06 Jun 2019*

### Features

- Options `--upgrade` and `--upgrade-package` are no longer mutually exclusive ({pr}`831`)
  -- by {user}`adamchainz`.

### Bug Fixes

- Fix `--generate-hashes` with bare VCS URLs ({pr}`812`)
  -- by {user}`jcushman`.
- Fix issues with `UnicodeError` when installing `pip-tools` from source in
  some systems ({pr}`816`) -- by {user}`AbdealiJK`.
- Respect `--pre` option in the input file ({pr}`822`)
  -- by {user}`atugushev`.
- Option `--upgrade-package` now works even if the output file does not exist ({pr}`831`)
  -- by {user}`adamchainz`.

## v3.7.0

*09 May 2019*

### Features

- Show progressbar on generation hashes in `pip-compile` verbose mode ({pr}`743`)
  -- by {user}`atugushev`.
- Add options `--cert` and `--client-cert` to `pip-sync` ({pr}`798`)
  -- by {user}`atugushev`.
- Add support for `--find-links` in `pip-compile` output ({pr}`793`)
  -- by {user}`estan` and {user}`atugushev`.
- Normalize «command to run» in `pip-compile` headers ({pr}`800`)
  -- by {user}`atugushev`.
- Support URLs as packages ({pr}`807`)
  -- by {user}`jcushman`, {user}`nim65s` and {user}`toejough`.

### Bug Fixes

- Fix replacing password to asterisks in `pip-compile` ({pr}`808`)
  -- by {user}`atugushev`.

## v3.6.1

*24 Apr 2019*

### Bug Fixes

- Fix `pip>=19.1` compatibility ({pr}`795`)
  -- by {user}`atugushev`.

## v3.6.0

*03 Apr 2019*

### Features

- Show less output on `pip-sync` with `--quiet` option ({pr}`765`)
  -- by {user}`atugushev`.
- Support the flag `--trusted-host` in `pip-sync` ({pr}`777`)
  -- by {user}`firebirdberlin`.

## v3.5.0

*13 Mar 2019*

### Features

- Show default index url provided by `pip` ({pr}`735`)
  -- by {user}`atugushev`.
- Add an option to allow enabling/disabling build isolation ({pr}`758`)
  -- by {user}`atugushev`.

### Bug Fixes

- Fix the output file for `pip-compile` with an explicit `setup.py` as source
  file ({pr}`731`) -- by {user}`atugushev`.
- Fix order issue with generated lock file when `hashes` and `markers` are
  used together ({pr}`763`) -- by {user}`milind-shakya-sp`.

## v3.4.0

*19 Feb 2019*

### Features

- Add option `--quiet` to `pip-compile` ({pr}`720`)
  -- by {user}`bendikro`.
- Emit the original command to the `pip-compile`'s header ({pr}`733`)
  -- by {user}`atugushev`.

### Bug Fixes

- Fix `pip-sync` to use pip script depending on a python version ({pr}`737`)
  -- by {user}`atugushev`.

## v3.3.2

*26 Jan 2019*

### Bug Fixes

- Fix `pip-sync` with a temporary requirement file on Windows ({pr}`723`)
  -- by {user}`atugushev`.
- Fix `pip-sync` to prevent uninstall of stdlib and dev packages ({pr}`718`)
  -- by {user}`atugushev`.

## v3.3.1

*24 Jan 2019*

- Re-release of 3.3.0 after fixing the deployment pipeline ({issue}`716`)
  -- by {user}`atugushev`.

## v3.3.0

*23 Jan 2019*

(Unreleased - Deployment pipeline issue, see 3.3.1)

### Features

- Added support of `pip` 19.0 ({pr}`715`)
  -- by {user}`atugushev`.
- Add `--allow-unsafe` to update instructions in the generated
  `requirements.txt` ({pr}`708`) -- by {user}`richafrank`.

### Bug Fixes

- Fix `pip-sync` to check hashes ({pr}`706`)
  -- by {user}`atugushev`.

## v3.2.0

*18 Dec 2018*

### Features

- Apply version constraints specified with package upgrade option
  (`-P, --upgrade-package`) ({pr}`694`)
  -- by {user}`richafrank`.

## v3.1.0

*05 Oct 2018*

### Features

- Added support of `pip` 18.1 ({pr}`689`)
  -- by {user}`vphilippon`.

## v3.0.0

*24 Sep 2018*

### Major Changes

- Update `pip-tools` for native `pip` 8, 9, 10 and 18 compatibility,
  un-vendoring `pip` to use the user-installed `pip` ({pr}`657` and {pr}`672`)
  -- by {user}`techalchemy`, {user}`suutari`, {user}`tysonclugg` and.
  {user}`vphilippon`

### Features

- Removed the dependency on the external library `first` ({pr}`676`)
  -- by {user}`jdufresne`.

## v2.0.2

*28 Apr 2018*

### Bug Fixes

- Added clearer error reporting when skipping pre-releases ({pr}`655`)
  -- by {user}`WoLpH`.

## v2.0.1

*15 Apr 2018*

### Bug Fixes

- Added missing package data from vendored pip, such as missing cacert.pem file
  -- by {user}`vphilippon`.

## v2.0.0

*15 Apr 2018*

### Major Changes

- Vendored `pip` 9.0.3 to keep compatibility for users with `pip` 10.0.0 ({pr}`644`)
  -- by {user}`vphilippon`.

### Features

- Improved the speed of `pip-compile --generate-hashes` by caching the hashes
  from an existing output file ({pr}`641`)
  -- by {user}`justicz`.
- Added a `pip-sync --user` option to restrict attention to user-local
  directory ({pr}`642`) -- by {user}`jbergknoff-10e`.
- Removed the hard dependency on setuptools ({pr}`645`)
  -- by {user}`vphilippon`.

### Bug Fixes

- The pip environment markers on top-level requirements in the source file
  (requirements.in) are now properly handled and will only be processed in the right
  environment ({pr}`647`)
  -- by {user}`JoergRittinger`.

## v1.11.0

*30 Nov 2017*

### Features

- Allow editable packages in requirements.in with
  `pip-compile --generate-hashes` ({pr}`524`) -- by {user}`jdufresne`.
- Allow for CA bundles with `pip-compile --cert` ({pr}`612`)
  -- by {user}`khwilson`.
- Improved `pip-compile` duration with large locally available editable
  requirement by skipping a copy to the cache ({pr}`583`)
  -- by {user}`costypetrisor`.
- Slightly improved the `NoCandidateFound` error message on potential causes ({pr}`614`)
  -- by {user}`vphilippon`.

### Bug Fixes

- Add `-markerlib` to the list of `PACKAGES_TO_IGNORE` of `pip-sync` ({pr}`613`).

## v1.10.2

*22 Nov 2017*

### Bug Fixes

- Fixed bug causing dependencies from invalid wheels for the current platform
  to be included ({pr}`571`).
- `pip-sync` will respect environment markers in the `requirements.txt` ({pr}`600`)
  -- by {user}`hazmat345`.
- Converted the ReadMe to have a nice description rendering on PyPI
  -- by {user}`bittner`.

## v1.10.1

*27 Sep 2017*

### Bug Fixes

- Fixed bug breaking `pip-sync` on Python 3, raising
  `TypeError: '<' not supported between instances of 'InstallRequirement' and
  'InstallRequirement'` ({pr}`570`).

## v1.10.0

*27 Sep 2017*

### Features

- `--generate-hashes` now generates hashes for all wheels, not only wheels for the
  currently running platform ({pr}`520`)
  -- by {user}`jdufresne`.
- Added a `-q`/`--quiet` argument to the `pip-sync` command to reduce log output.

### Bug Fixes

- Fixed bug where unsafe packages would get pinned in generated requirements
  files when `--allow-unsafe` was not set ({pr}`517`)
  -- by {user}`dschaller`.
- Fixed bug where editable PyPI dependencies would have a `download_dir` and be exposed
  to `git-checkout-index`, (thus losing their VCS directory) and
  `python setup.py egg_info` fails ({pr}`385`) and {pr}`538`)
  -- by {user}`blueyed` and {user}`dfee`.
- Fixed bug where some primary dependencies were annotated with "via" info
  comments ({pr}`542`) -- by {user}`quantus`.
- Fixed bug where pkg-resources would be removed by `pip-sync` in Ubuntu ({pr}`555`)
  -- by {user}`cemsbr`.
- Fixed bug where the resolver would sometime not stabilize on requirements specifying
  extras ({pr}`566`)
  -- by {user}`vphilippon`.
- Fixed an unicode encoding error when distribution package contains non-ASCII file
  names ({pr}`567`)
  -- by {user}`suutari`.
- Fixed package hashing doing unnecessary unpacking ({pr}`557`)
  -- by {user}`suutari-ai`.

## v1.9.0

*12 Apr 2017*

### Features

- Added ability to read requirements from `setup.py` instead of just `requirements.in`
  ({pr}`418`)
  -- by {user}`tysonclugg` and {user}`majuscule`.
- Added a `--max-rounds` argument to the `pip-compile` command to allow for
  solving large requirement sets ({pr}`472`)
  -- by {user}`derek-miller`.
- Exclude unsafe packages' dependencies when `--allow-unsafe` is not in use ({pr}`441`)
  -- by {user}`jdufresne`.
- Exclude irrelevant pip constraints ({pr}`471`)
  -- by {user}`derek-miller`.
- Allow control over emitting trusted-host to the compiled requirements ({pr}`448`)
  -- by {user}`tonyseek`.
- Allow running as a Python module ({pr}`461`)
  -- by {user}`AndreLouisCaron`.
- Preserve environment markers in generated `requirements.txt` ({pr}`460`)
  -- by {user}`barrywhart`.

### Bug Fixes

- Fixed the `--upgrade-package` option to respect the given package list to
  update ({pr}`491`).
- Fixed the default output file name when the source file has no extension
  ({pr}`488`) -- by {user}`vphilippon`.
- Fixed crash on editable requirements introduced in 1.8.2.
- Fixed duplicated `--trusted-host`, `--extra-index-url` and `--index-url` in
  the generated requirements.

## v1.8.2

*28 Mar 2017*

- Regression fix: editable reqs were losing their dependencies after first
  round ({pr}`476`) -- by {user}`mattlong`.
- Remove duplicate index urls in generated `requirements.txt` ({pr}`468`)
  -- by {user}`majuscule`.

## v1.8.1

*22 Mar 2017*

- Recalculate secondary dependencies between rounds ({pr}`378`)
- Calculated dependencies could be left with wrong candidates when toplevel requirements
  happen to be also pinned in sub-dependencies ({pr}`450`)
- Fix duplicate entries that could happen in generated `requirements.txt` ({pr}`427`)
- Gracefully report invalid pip version ({pr}`457`)
- Fix capitalization in the generated `requirements.txt`, packages will always be
  lowercased ({pr}`452`)

## v1.8.0

*17 Nov 2016*

- Adds support for upgrading individual packages with a new option `--upgrade-package`.
  To upgrade a _specific_ package to the latest or a specific version use
  `--upgrade-package <pkg>`. To upgrade all packages, you can still use
  `pip-compile --upgrade`. ({pr}`409`)
- Adds support for pinning dependencies even further by including the hashes
  found on PyPI at compilation time, which will be re-checked when dependencies
  are installed at installation time. This adds protection against packages
  that are tampered with. ({pr}`383`)
- Improve support for extras, like `hypothesis[django]`
- Drop support for `pip < 8`

## v1.7.1

*20 Oct 2016*

- Add `--allow-unsafe` option (#377)

## v1.7.0

*06 Jul 2016*

- Add compatibility with `pip >= 8.1.2` (#374)
  -- by {user}`jmbowman`

## v1.6.5

*11 May 2016*

- Add warning that `pip >= 8.1.2` is not supported until 1.7.x is out

## v1.6.4

*03 May 2016*

- Incorporate fix for atomic file saving behaviour on the Windows platform (see {issue}`351`)

## v1.6.3

*02 May 2016*

- PyPI won't let me upload 1.6.2

## v1.6.2

*02 May 2016*

- Respect pip configuration from `pip.{ini,conf}`
- Fixes for atomic-saving of output files on Windows (see {issue}`351`)

## v1.6.1

*06 Apr 2016*

### Minor Changes

- `pip-sync` now supports being invoked from within and outside an activated virtualenv
  (see {issue}`317`)
- `pip-compile`: support `-U` as a shorthand for `--upgrade`
- `pip-compile`: support pip's `--no-binary` and `--binary-only` flags

### Bug Fixes

- Change header format of output files to mention all input files

## v1.6

*05 Feb 2016*

### Major Changes

- `pip-compile` will by default try to fulfill package specs by looking at a
  previously compiled output file first, before checking PyPI. This means
  `pip-compile` will only update the `requirements.txt` when it absolutely has
  to. To get the old behaviour (picking the latest version of all packages from
  PyPI), use the new `--upgrade` option.

### Minor Changes

- Bugfix where `pip-compile` would lose "via" info when on pip 8 (see {issue}`313`)
- Ensure cache dir exists (see {issue}`315`)

## v1.5

*23 Jan 2016*

- Add support for `pip >= 8`
- Drop support for `pip < 7`
- Fix bug where `pip-sync` fails to uninstall packages if you're using the `--no-index`
  (or other) flags

## v1.4.5

*20 Jan 2016*

- Add `--no-index` flag to `pip-compile` to avoid emitting `--index-url` into
  the output (useful if you have configured a different index in your global
  `~/.pip/pip.conf`, for example)
- Fix: ignore stdlib backport packages, like `argparse`, when listing which packages
  will be installed/uninstalled ({issue}`286`)
- Fix `pip-sync` failed uninstalling packages when using `--find-links` ({issue}`298`)
- Explicitly error when pip-tools is used with pip 8.0+ (for now)

## v1.4.4

*11 Jan 2016*

- Fix: unintended change in behaviour where packages installed by `pip-sync` could
  accidentally get upgraded under certain conditions, even though the `requirements.txt`
  would dictate otherwise (see {issue}`290`)

## v1.4.3

*06 Jan 2016*

- Fix: add `--index-url` and `--extra-index-url` options to `pip-sync`
- Fix: always install using `--upgrade` flag when running `pip-sync`

## v1.4.2

*13 Dec 2015*

- Fix bug where umask was ignored when writing requirement files ({issue}`268`)

## v1.4.1

*13 Dec 2015*

- Fix bug where successive invocations of `pip-sync` with editables kept
  uninstalling/installing them (fixes {issue}`270`)

## v1.4.0

*13 Dec 2015*

- Add command line option `-f` / `--find-links`
- Add command line option `--no-index`
- Add command line alias `-n` (for `--dry-run`)
- Fix a unicode issue

## v1.3.0

*08 Dec 2015*

- Support multiple requirement files to `pip-compile`
- Support requirements from stdin for `pip-compile`
- Support `--output-file` option on `pip-compile`, to redirect output to a file
  (or stdout)

## v1.2.0

*30 Nov 2015*

- Add CHANGELOG :)
- Support pip-sync'ing editable requirements
- Support extras properly (i.e. `package[foo]` syntax)

(Anything before 1.2.0 was not recorded.)


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Code of Conduct

As contributors and maintainers of the Jazzband projects, and in the interest
of fostering an open and welcoming community, we pledge to respect all people
who contribute through reporting issues, posting feature requests, updating
documentation, submitting pull requests or patches, and other activities.

We are committed to making participation in the Jazzband a harassment-free
experience for everyone, regardless of the level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, religion, or nationality.

Examples of unacceptable behavior by participants include:

- The use of sexualized language or imagery
- Personal attacks
- Trolling or insulting/derogatory comments
- Public or private harassment
- Publishing other's private information, such as physical or electronic
  addresses, without explicit permission
- Other unethical or unprofessional conduct

The Jazzband roadies have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

By adopting this Code of Conduct, the roadies commit themselves to fairly and
consistently applying these principles to every aspect of managing the jazzband
projects. Roadies who do not follow or enforce the Code of Conduct may be
permanently removed from the Jazzband roadies.

This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the roadies at `roadies@jazzband.co`. All complaints
will be reviewed and investigated and will result in a response that is deemed
necessary and appropriate to the circumstances. Roadies are obligated to
maintain confidentiality with regard to the reporter of an incident.

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.3.0, available at
[https://contributor-covenant.org/version/1/3/0/][version]

[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/3/0/


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to `pip-tools`

<!-- sphinx-inclusion-post-this-line -->

[![Jazzband](https://jazzband.co/static/img/jazzband.svg)](https://jazzband.co)

This is a [Jazzband](https://jazzband.co) project. By contributing you agree
to abide by the [Contributor Code of Conduct][coc]
and follow the [guidelines](https://jazzband.co/about/guidelines).

[coc]: https://jazzband.co/about/conduct

## Project Contribution Guidelines

Here are a few additional or emphasized guidelines to follow when contributing
to `pip-tools`:

- If you need to have a virtualenv outside of `tox`, it is possible to reuse
  its configuration to provision it with [tox devenv].
- Always provide tests for your changes and run `tox -p all` to make sure they
  are passing the checks locally.
- Give a clear one-line description in the PR (that the maintainers can add to
  [CHANGELOG] afterwards).
- Wait for the review of at least one other contributor before merging (even if
  you're a Jazzband member).
- Before merging, assign the PR to a milestone for a version to help with the
  release process.

The only exception to those guidelines is for trivial changes, such as
documentation corrections or contributions that do not change pip-tools itself.

Contributions following these guidelines are always welcomed, encouraged and
appreciated.

[tox devenv]: <https://tox.wiki/en/latest/reference/cli.html#tox-devenv-(d)>

### LLM Generated Contributions

Contributors are free to use whatever tools they like, but we have some
additional guidance for LLM-assisted contributions.

When interacting in pip-tools spaces (issues, pull requests, matrix, discord, etc.),
do not use LLMs to speak for you, except for translation or grammar edits.
This includes the creation of changelogs and PR descriptions.
Human-to-human communication is foundational to open source communities.

> [!CAUTION]
> In extreme cases, low quality PRs may be closed as spam.

#### Responsibility

Remember that you, not the LLM, are responsible for your contributions.
Be ready to discuss your changes.
Do not submit code you have not reviewed.

Do your best to follow the conventions and standards of the project.
Make sure your code really works.
Be thoughtful about testing and documentation.

Try to make your code brief, and recognize when less is more.

#### Autonomous Code Submissions

The use of agents which write code and submit pull requests without human review
is not permitted.

#### Pull Request Templates

Please do not replace the pull request template, which is part of the
maintainers' process.

### The `good first issue` label

The [`good first issue` label] is used to designate items which are being left
for new contributors.
They're a great way to get onboarded into the project and learn.

Having an LLM resolve one of these issues does not help anyone learn.
Therefore, please be considerate of those who may benefit from these
opportunities, and refrain from asking an LLM to produce a complete solution.

## Project Release Process

Releases require approval by a member of the [`pip-tools-leads` team].

Commands given below may assume that your fork is named `origin` in git
remotes and the main repo is named `upstream`.

This is the current release process:

- Create a branch for the release. _e.g., `release/v3.4.0`_.
- Use `towncrier` to update the [CHANGELOG], _e.g.,
  `towncrier build --version v3.4.0`_.
- Push the branch to your fork, _e.g.,
  `git push -u origin release/v3.4.0`_, and create a pull request.
- Merge the pull request after the changes are approved.
- Make sure that the tests/CI still pass.
- Fetch the latest changes to `main` locally.
- Create an unsigned tag with the release version number prefixed with a
  `v`, _e.g., `git tag -a v3.4.0 -m v3.4.0`_, and push it to `upstream`.
- Create a GitHub Release, populated with a copy of the changelog and set
  to "Create a discussion for this release" in the `Announcements`
  category.
  Some of the markdown will need to be reformatted into GFM.
  The release title and tag should be the newly created tag.
- The [GitHub Release Workflow] will trigger off of the release to
  publish to PyPI. A member of the [`pip-tools-leads` team] must approve
  the publication step.
- Once the release to PyPI is confirmed, close the milestone.
- Publish any release notifications,
  _e.g., pip-tools matrix channel, discuss.python.org, bluesky, mastodon,
  pypa Discord_.

[changelog]: ./CHANGELOG.md
[GitHub Release Workflow]:
https://github.com/jazzband/pip-tools/actions/workflows/release.yml
[`pip-tools-leads` team]:
https://github.com/orgs/jazzband/teams/pip-tools-leads
[LLM Policy Discussion]:
https://github.com/jazzband/pip-tools/discussions/2278
[`good first issue` label]:
https://github.com/jazzband/pip-tools/labels/good%20first%20issue%22


================================================
FILE: LICENSE
================================================
BSD 3-Clause License

Copyright (c). All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.

    3. Neither the name of pip-tools nor the names of its contributors may be
       used to endorse or promote products derived from this software without
       specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


================================================
FILE: MANIFEST.in
================================================
# do not include the `.git_archival.txt` file in sdist builds from repo source
# this avoids setuptools-scm warnings on development builds
exclude .git_archival.txt


================================================
FILE: README.md
================================================
<!-- pyml disable-next-line first-line-heading -->
[![jazzband-image]][jazzband]
[![pypi][pypi-image]][pypi]
[![pyversions][pyversions-image]][pyversions]
[![pre-commit][pre-commit-image]][pre-commit]
[![buildstatus-gha][buildstatus-gha-image]][buildstatus-gha]
[![codecov][codecov-image]][codecov]
[![Matrix Room Badge]][Matrix Room]
[![Matrix Space Badge]][Matrix Space]
[![discord-chat-image]][discord-chat]

# pip-tools = pip-compile + pip-sync

A set of command line tools to help you keep your `pip`-based packages fresh,
even when you've pinned them. You do pin them, right? (In building your Python
application and its dependencies for production, you want to make sure that
your builds are predictable and deterministic.)

[![pip-tools overview for phase II][pip-tools-overview]][pip-tools-overview]

## Installation

Similar to `pip`, `pip-tools` must be installed in each of your project's
[virtual environments](https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments):

```console
$ source /path/to/venv/bin/activate
(venv) $ python -m pip install pip-tools
```

**Note**: all of the remaining example commands assume you've activated your
project's virtual environment.

## Example usage for `pip-compile`

The `pip-compile` command lets you compile a `requirements.txt` file from
your dependencies, specified in either `pyproject.toml`, `setup.cfg`,
`setup.py`, or `requirements.in`.

Run it with `pip-compile` or `python -m piptools compile` (or
`pipx run --spec pip-tools pip-compile` if `pipx` was installed with the
appropriate Python version). If you use multiple Python versions, you can also
run `py -X.Y -m piptools compile` on Windows and
`pythonX.Y -m piptools compile` on other systems.

`pip-compile` should be run from the same virtual environment as your
project so conditional dependencies that require a specific Python version,
or other environment markers, resolve relative to your project's
environment.

**Note**: If `pip-compile` finds an existing `requirements.txt` file that
fulfils the dependencies then no changes will be made, even if updates are
available. To compile from scratch, first delete the existing
`requirements.txt` file, or see
[Updating requirements](#updating-requirements)
for alternative approaches.

### Requirements from `pyproject.toml`

The `pyproject.toml` file is the
[latest standard](https://peps.python.org/pep-0621/) for configuring
packages and applications, and is recommended for new projects. `pip-compile`
supports both installing your `project.dependencies` as well as your
`project.optional-dependencies`. Thanks to the fact that this is an
official standard, you can use `pip-compile` to pin the dependencies
in projects that use modern standards-adhering packaging tools like
[Setuptools](https://setuptools.pypa.io), [Hatch](https://hatch.pypa.io/)
or [flit](https://flit.pypa.io/).

Suppose you have a 'foobar' Python application that is packaged using
`Setuptools`, and you want to pin it for production. You can declare the
project metadata as:

```toml
[build-system]
requires = ["setuptools", "setuptools-scm"]
build-backend = "setuptools.build_meta"

[project]
requires-python = ">=3.9"
name = "foobar"
dynamic = ["dependencies", "optional-dependencies"]

[tool.setuptools.dynamic]
dependencies = { file = ["requirements.in"] }
optional-dependencies.test = { file = ["requirements-test.txt"] }

```

If you have a Django application that is packaged using `Hatch`, and you
want to pin it for production. You also want to pin your development tools
in a separate pin file. You declare `django` as a dependency and create an
optional dependency `dev` that includes `pytest`:

```toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-cool-django-app"
version = "42"
dependencies = ["django"]

[project.optional-dependencies]
dev = ["pytest"]
```

You can produce your pin files as easily as:

```console
$ pip-compile -o requirements.txt pyproject.toml
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --output-file=requirements.txt pyproject.toml
#
asgiref==3.6.0
    # via django
django==4.1.7
    # via my-cool-django-app (pyproject.toml)
sqlparse==0.4.3
    # via django

$ pip-compile --extra dev -o dev-requirements.txt pyproject.toml
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --extra=dev --output-file=dev-requirements.txt pyproject.toml
#
asgiref==3.6.0
    # via django
attrs==22.2.0
    # via pytest
django==4.1.7
    # via my-cool-django-app (pyproject.toml)
exceptiongroup==1.1.1
    # via pytest
iniconfig==2.0.0
    # via pytest
packaging==23.0
    # via pytest
pluggy==1.0.0
    # via pytest
pytest==7.2.2
    # via my-cool-django-app (pyproject.toml)
sqlparse==0.4.3
    # via django
tomli==2.0.1
    # via pytest
```

This is great for both pinning your applications, but also to keep the CI
of your open-source Python package stable.

### Requirements from `setup.py` and `setup.cfg`

`pip-compile` has also full support for `setup.py`- and
`setup.cfg`-based projects that use `setuptools`.

Just define your dependencies and extras as usual and run
`pip-compile` as above.

### Requirements from `requirements.in`

You can also use plain text files for your requirements (e.g. if you don't
want your application to be a package). To use a `requirements.in` file to
declare the Django dependency:

```text
# requirements.in
django
```

Now, run `pip-compile requirements.in`:

```console
$ pip-compile requirements.in
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile requirements.in
#
asgiref==3.6.0
    # via django
django==4.1.7
    # via -r requirements.in
sqlparse==0.4.3
    # via django
```

And it will produce your `requirements.txt`, with all the Django dependencies
(and all underlying dependencies) pinned.

(updating-requirements)=

### Updating requirements

`pip-compile` generates a `requirements.txt` file using the latest versions
that fulfil the dependencies you specify in the supported files.

If `pip-compile` finds an existing `requirements.txt` file that fulfils the
dependencies then no changes will be made, even if updates are available.

To force `pip-compile` to update all packages in an existing
`requirements.txt`, run `pip-compile --upgrade`.

To update a specific package to the latest or a specific version use the
`--upgrade-package` or `-P` flag:

```console
# only update the django package
$ pip-compile --upgrade-package django

# update both the django and requests packages
$ pip-compile --upgrade-package django --upgrade-package requests

# update the django package to the latest, and requests to v2.0.0
$ pip-compile --upgrade-package django --upgrade-package requests==2.0.0
```

You can combine `--upgrade` and `--upgrade-package` in one command, to
provide constraints on the allowed upgrades. For example to upgrade all
packages whilst constraining requests to the latest version less than 3.0:

<!-- pyml disable-num-lines 2 commands-show-output -->
```console
$ pip-compile --upgrade --upgrade-package 'requests<3.0'
```

### Understanding output file behavior

When you run `pip-compile`, it reads any existing output file (e.g.,
`requirements.txt`) and uses the versions specified there as constraints.
This ensures that the output is stable -- `pip-compile` will prefer to
use existing pinned versions.

When upgrading packages or adding new packages to the input,
it is possible for the existing pins to conflict with new packages. In such cases,
`pip-compile` will update the pins and emit a warning
(e.g., `Discarding foo=1.2.3 to proceed`).

In order to resolve dependencies afresh, `pip-compile` provides the following options:

- `--upgrade` / `-U` flag to upgrade all packages
- `--upgrade-package <package>`/`-P <package>` to upgrade specific packages

### Using hashes

If you would like to use _Hash-Checking Mode_ available in `pip` since
version 8.0, `pip-compile` offers `--generate-hashes` flag:

<!-- pyml disable-num-lines 18 line-length -->
```console
$ pip-compile --generate-hashes requirements.in
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --generate-hashes requirements.in
#
asgiref==3.6.0 \
    --hash=sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac \
    --hash=sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506
    # via django
django==4.1.7 \
    --hash=sha256:44f714b81c5f190d9d2ddad01a532fe502fa01c4cb8faf1d081f4264ed15dcd8 \
    --hash=sha256:f2f431e75adc40039ace496ad3b9f17227022e8b11566f4b363da44c7e44761e
    # via -r requirements.in
sqlparse==0.4.3 \
    --hash=sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34 \
    --hash=sha256:69ca804846bb114d2ec380e4360a8a340db83f0ccf3afceeb1404df028f57268
    # via django
```

### Output File

To output the pinned requirements in a filename other than
`requirements.txt`, use `--output-file`. This might be useful for compiling
multiple files, for example with different constraints on django to test a
library with both versions using [tox](https://tox.readthedocs.io/en/latest/):

<!-- pyml disable-num-lines 2 commands-show-output -->
```console
$ pip-compile --upgrade-package 'django<1.0' --output-file requirements-django0x.txt
$ pip-compile --upgrade-package 'django<2.0' --output-file requirements-django1x.txt
```

Or to output to standard output, use `--output-file=-`:

<!-- pyml disable-num-lines 2 commands-show-output -->
```console
$ pip-compile --output-file=- > requirements.txt
$ pip-compile - --output-file=- < requirements.in > requirements.txt
```

### Forwarding options to `pip`

Any valid `pip` flags or arguments may be passed on with `pip-compile`'s
`--pip-args` option, e.g.

<!-- pyml disable-num-lines 2 commands-show-output -->
```console
$ pip-compile requirements.in --pip-args "--retries 10 --timeout 30"
```

### Configuration

You can define project-level defaults for `pip-compile` and `pip-sync` by
writing them to a configuration file in the same directory as your requirements
input files (or the current working directory if piping input from stdin).
By default, both `pip-compile` and `pip-sync` will look first
for a `.pip-tools.toml` file and then in your `pyproject.toml`. You can
also specify an alternate TOML configuration file with the `--config` option.

It is possible to specify configuration values both globally and command-
specific.
For example, to by default generate `pip` hashes in the resulting
requirements file output, you can specify in a configuration file:

```toml
[tool.pip-tools]
generate-hashes = true
```

Options to `pip-compile` and `pip-sync` that may be used more than once
must be defined as lists in a configuration file, even if they only have one
value.

`pip-tools` supports default values for [all valid command-line
flags](/cli/index.md) of its subcommands. Configuration keys may contain
underscores instead of dashes, so the above could also be specified in this
format:

```toml
[tool.pip-tools]
generate_hashes = true
```

Configuration defaults specific to `pip-compile` and `pip-sync` can be put
beneath separate sections. For example, to by default perform a dry-run with
`pip-compile`:

```toml
[tool.pip-tools.compile] # "sync" for pip-sync
dry-run = true
```

This does not affect the `pip-sync` command, which also has a `--dry-run`
option.
Note that local settings take preference over the global ones of the same name,
whenever both are declared, thus this would also make `pip-compile` generate
hashes, but discard the global dry-run setting:

```toml
[tool.pip-tools]
generate-hashes = true
dry-run = true

[tool.pip-tools.compile]
dry-run = false
```

You might be wrapping the `pip-compile` command in another script. To avoid
confusing consumers of your custom script you can override the update command
generated at the top of requirements files by setting the
`CUSTOM_COMPILE_COMMAND` environment variable.

```console
$ CUSTOM_COMPILE_COMMAND="./pipcompilewrapper" pip-compile requirements.in
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    ./pipcompilewrapper
#
asgiref==3.6.0
    # via django
django==4.1.7
    # via -r requirements.in
sqlparse==0.4.3
    # via django
```

### Workflow for layered requirements

If you have different environments that you need to install different but
compatible packages for, then you can create layered requirements files and use
one layer to constrain the other.

For example, if you have a Django project where you want the newest `2.1`
release in production and when developing you want to use the Django debug
toolbar, then you can create two `*.in` files, one for each layer:

```text
# requirements.in
django<2.2
```

At the top of the development requirements `dev-requirements.in` you use `-c
requirements.txt` to constrain the dev requirements to packages already
selected for production in `requirements.txt`.

```text
# dev-requirements.in
-c requirements.txt
django-debug-toolbar<2.2
```

First, compile `requirements.txt` as usual:

```text
$ pip-compile
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile
#
django==2.1.15
    # via -r requirements.in
pytz==2023.3
    # via django
```

Now compile the dev requirements and the `requirements.txt` file is used as
a constraint:

```console
$ pip-compile dev-requirements.in
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile dev-requirements.in
#
django==2.1.15
    # via
    #   -c requirements.txt
    #   django-debug-toolbar
django-debug-toolbar==2.1
    # via -r dev-requirements.in
pytz==2023.3
    # via
    #   -c requirements.txt
    #   django
sqlparse==0.4.3
    # via django-debug-toolbar
```

As you can see above, even though a `2.2` release of Django is available, the
dev requirements only include a `2.1` version of Django because they were
constrained. Now both compiled requirements files can be installed safely in
the dev environment.

To install requirements in production stage use:

<!-- pyml disable-num-lines 2 commands-show-output -->
```console
$ pip-sync
```

You can install requirements in development stage by:

<!-- pyml disable-num-lines 2 commands-show-output -->
```console
$ pip-sync requirements.txt dev-requirements.txt
```

### Version control integration

You might use `pip-compile` as a hook for the
[pre-commit](https://github.com/pre-commit/pre-commit).
See [pre-commit docs](https://pre-commit.com/) for instructions.
Sample `.pre-commit-config.yaml`:

```yaml
repos:
  - repo: https://github.com/jazzband/pip-tools
    rev: 7.4.1
    hooks:
      - id: pip-compile
```

You might want to customize `pip-compile` args by configuring `args` and/or
`files`, for example:

```yaml
repos:
  - repo: https://github.com/jazzband/pip-tools
    rev: 7.4.1
    hooks:
      - id: pip-compile
        files: ^requirements/production\.(in|txt)$
        args: [--index-url=https://example.com, requirements/production.in]
```

If you have multiple requirement files make sure you create a hook for each
file.

```yaml
repos:
  - repo: https://github.com/jazzband/pip-tools
    rev: 7.4.1
    hooks:
      - id: pip-compile
        name: pip-compile setup.py
        files: ^(setup\.py|requirements\.txt)$
      - id: pip-compile
        name: pip-compile requirements-dev.in
        args: [requirements-dev.in]
        files: ^requirements-dev\.(in|txt)$
      - id: pip-compile
        name: pip-compile requirements-lint.in
        args: [requirements-lint.in]
        files: ^requirements-lint\.(in|txt)$
      - id: pip-compile
        name: pip-compile requirements.in
        args: [requirements.in]
        files: ^requirements\.(in|txt)$
```

### Example usage for `pip-sync`

Now that you have a `requirements.txt`, you can use `pip-sync` to update
your virtual environment to reflect exactly what's in there. This will
install/upgrade/uninstall everything necessary to match the
`requirements.txt` contents.

Run it with `pip-sync` or `python -m piptools sync`. If you use multiple
Python versions, you can also run `py -X.Y -m piptools sync` on Windows and
`pythonX.Y -m piptools sync` on other systems.

`pip-sync` must be installed into and run from the same virtual
environment as your project to identify which packages to install
or upgrade.

**Be careful**: `pip-sync` is meant to be used only with a
`requirements.txt` generated by `pip-compile`.

```console
$ pip-sync
Uninstalling flake8-2.4.1:
    Successfully uninstalled flake8-2.4.1
Collecting click==4.1
    Downloading click-4.1-py2.py3-none-any.whl (62kB)
    100% |................................| 65kB 1.8MB/s
    Found existing installation: click 4.0
    Uninstalling click-4.0:
        Successfully uninstalled click-4.0
Successfully installed click-4.1
```

To sync multiple `*.txt` dependency lists, just pass them in via command
line arguments, e.g.

<!-- pyml disable-num-lines 2 commands-show-output -->
```console
$ pip-sync dev-requirements.txt requirements.txt
```

Passing in empty arguments would cause it to default to `requirements.txt`.

Any valid `pip install` flags or arguments may be passed with `pip-sync`'s
`--pip-args` option, e.g.

<!-- pyml disable-num-lines 2 commands-show-output -->
```console
$ pip-sync requirements.txt --pip-args "--no-cache-dir --no-deps"
```

**Note**: `pip-sync` will not upgrade or uninstall packaging tools like
`setuptools`, `pip`, or `pip-tools` itself.
Use `python -m pip install --upgrade` to upgrade those packages.

### Should I commit `requirements.in` and `requirements.txt` to source control?

Generally, yes. If you want a reproducible environment installation available
from your source control, then yes, you should commit both `requirements.in`
and `requirements.txt` to source control.

Note that if you are deploying on multiple Python environments (read the
section below), then you must commit a separate output file for each Python
environment.
We suggest to use the `{env}-requirements.txt` format
(ex: `win32-py3.7-requirements.txt`, `macos-py3.10-requirements.txt`,
etc.).

### Cross-environment usage of `requirements.in`/`requirements.txt` and `pip-compile`

The dependencies of a package can change depending on the Python environment in
which it is installed. Here, we define a Python environment as the combination
of Operating System, Python version (3.7, 3.8, etc.), and Python implementation
(CPython, PyPy, etc.). For an exact definition, refer to the possible
combinations of [PEP 508 environment markers][environment-markers].

As the resulting `requirements.txt` can differ for each environment, users must
execute `pip-compile` **on each Python environment separately** to generate a
`requirements.txt` valid for each said environment. The same `requirements.in`
can be used as the source file for all environments, using
[PEP 508 environment markers][environment-markers] as needed, the same way it
would be done for regular `pip` cross-environment usage.

If the generated `requirements.txt` remains exactly the same for all Python
environments, then it can be used across Python environments safely. **But**
users should be careful as any package update can introduce
environment-dependent dependencies, making any newly generated
`requirements.txt` environment-dependent too.
As a general rule, it's advised that users should still always execute
`pip-compile` on each targeted Python environment to avoid issues.

### Maximizing reproducibility

`pip-tools` is a great tool to improve the reproducibility of builds.
But there are a few things to keep in mind.

- `pip-compile` will produce different results in different environments as
  described in the previous section.
- `pip` must be used with the `PIP_CONSTRAINT` environment variable to lock
  dependencies in build environments as documented in
  [#8439](https://github.com/pypa/pip/issues/8439).
- Dependencies come from many sources.

Continuing the `pyproject.toml` example from earlier, creating a single lock
file could be done like:

<!-- pyml disable-num-lines 7 line-length -->
```console
$ pip-compile --all-build-deps --all-extras --output-file=constraints.txt --strip-extras pyproject.toml
#
# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
#    pip-compile --all-build-deps --all-extras --output-file=constraints.txt --strip-extras pyproject.toml
#
asgiref==3.5.2
    # via django
attrs==22.1.0
    # via pytest
backports-zoneinfo==0.2.1
    # via django
django==4.1
    # via my-cool-django-app (pyproject.toml)
editables==0.3
    # via hatchling
hatchling==1.11.1
    # via my-cool-django-app (pyproject.toml::build-system.requires)
iniconfig==1.1.1
    # via pytest
packaging==21.3
    # via
    #   hatchling
    #   pytest
pathspec==0.10.2
    # via hatchling
pluggy==1.0.0
    # via
    #   hatchling
    #   pytest
py==1.11.0
    # via pytest
pyparsing==3.0.9
    # via packaging
pytest==7.1.2
    # via my-cool-django-app (pyproject.toml)
sqlparse==0.4.2
    # via django
tomli==2.0.1
    # via
    #   hatchling
    #   pytest
```

Some build backends may also request build dependencies dynamically using the
`get_requires_for_build_` hooks described in [PEP 517] and [PEP 660].
This will be indicated in the output with one of the following suffixes:

- `(pyproject.toml::build-system.backend::editable)`
- `(pyproject.toml::build-system.backend::sdist)`
- `(pyproject.toml::build-system.backend::wheel)`

### Other useful tools

- [pip-compile-multi](https://pip-compile-multi.rtfd.io) - pip-compile command
  wrapper for multiple cross-referencing requirements files.
- [pipdeptree](https://github.com/tox-dev/pipdeptree) to print the dependency
  tree of the installed packages.
- `requirements.in`/`requirements.txt` syntax highlighting:
  - [requirements.txt.vim](https://github.com/raimon49/requirements.txt.vim)
    for Vim.
  - [Python extension for VS Code].
  - [pip-requirements.el](https://github.com/Wilfred/pip-requirements.el) for
    Emacs.

[Python extension for VS Code]:
https://marketplace.visualstudio.com/items?itemName=ms-python.python

### Deprecations

This section lists `pip-tools` features that are currently deprecated.

- In the next major release, the `--allow-unsafe` behavior will be enabled by
  default (https://github.com/jazzband/pip-tools/issues/989).
  Use `--no-allow-unsafe` to keep the old behavior. It is recommended
  to pass `--allow-unsafe` now to adapt to the upcoming change.
- The legacy resolver is deprecated and will be removed in future versions.
  The new default is `--resolver=backtracking`.
- In the next major release, the `--strip-extras` behavior will be enabled by
  default (https://github.com/jazzband/pip-tools/issues/1613).
  Use `--no-strip-extras` to keep the old behavior.

### A Note on Resolvers

You can choose from either default backtracking resolver or the deprecated
legacy resolver.

The legacy resolver will occasionally fail to resolve dependencies. The
backtracking resolver is more robust, but can take longer to run in general.

You can continue using the legacy resolver with `--resolver=legacy` although
note that it is deprecated and will be removed in a future release.

[jazzband]: https://jazzband.co/
[jazzband-image]: https://jazzband.co/static/img/badge.svg
[pypi]: https://pypi.org/project/pip-tools/
[pypi-image]: https://img.shields.io/pypi/v/pip-tools.svg
[pyversions]: https://pypi.org/project/pip-tools/
[pyversions-image]: https://img.shields.io/pypi/pyversions/pip-tools.svg
[pre-commit]: https://results.pre-commit.ci/latest/github/jazzband/pip-tools/main
[pre-commit-image]: https://results.pre-commit.ci/badge/github/jazzband/pip-tools/main.svg
[buildstatus-gha]: https://github.com/jazzband/pip-tools/actions?query=workflow%3ACI
[buildstatus-gha-image]: https://github.com/jazzband/pip-tools/workflows/CI/badge.svg
[codecov]: https://codecov.io/gh/jazzband/pip-tools
[codecov-image]: https://codecov.io/gh/jazzband/pip-tools/branch/main/graph/badge.svg
[Matrix Room Badge]: https://img.shields.io/matrix/pip-tools:matrix.org?label=Discuss%20on%20Matrix%20at%20%23pip-tools%3Amatrix.org&logo=matrix&server_fqdn=matrix.org&style=flat
[Matrix Room]: https://matrix.to/#/%23pip-tools:matrix.org
[Matrix Space Badge]: https://img.shields.io/matrix/jazzband:matrix.org?label=Discuss%20on%20Matrix%20at%20%23jazzband%3Amatrix.org&logo=matrix&server_fqdn=matrix.org&style=flat
[Matrix Space]: https://matrix.to/#/%23jazzband:matrix.org
[pip-tools-overview]: https://github.com/jazzband/pip-tools/raw/main/img/pip-tools-overview.svg
[environment-markers]: https://peps.python.org/pep-0508/#environment-markers
[PEP 517]: https://peps.python.org/pep-0517/
[PEP 660]: https://peps.python.org/pep-0660/
[discord-chat]: https://discord.gg/pypa
[discord-chat-image]: https://img.shields.io/discord/803025117553754132?label=Discord%20chat%20%23pip-tools&style=flat-square


================================================
FILE: changelog.d/.draft_changelog_partial.md
================================================
```{towncrier-draft-entries}
DRAFT_VERSION
```


================================================
FILE: changelog.d/.gitignore
================================================
*
!.gitignore
!.towncrier_template.md.jinja
!.draft_changelog_partial.md
!README.md
!*.afterword
!*.afterword.md
!*.afterword.*.md
!*.bugfix
!*.bugfix.md
!*.bugfix.*.md
!*.breaking
!*.breaking.md
!*.breaking.*.md
!*.contrib
!*.contrib.md
!*.contrib.*.md
!*.deprecation
!*.deprecation.md
!*.deprecation.*.md
!*.doc
!*.doc.md
!*.doc.*.md
!*.feature
!*.feature.md
!*.feature.*.md
!*.highlights
!*.highlights.md
!*.highlights.*.md
!*.misc
!*.misc.md
!*.misc.*.md
!*.packaging
!*.packaging.md
!*.packaging.*.md


================================================
FILE: changelog.d/.towncrier_template.md.jinja
================================================
{%- set is_draft_preview = versiondata["version"] == "DRAFT_VERSION" -%}
{%- set special_category_admonitions = {
  'afterword': 'tip',
  'highlights': 'important',
} -%}

{%- if is_draft_preview -%}
## Unreleased Changes
{% else -%}
## {{ versiondata["version"] }}
{% endif %}

*{%- if is_draft_preview -%}Generated for preview on {% endif -%}{{ versiondata["date"] }}*

{% for section, _ in sections.items() %}
{% if sections[section] %}
{% for category, val in definitions.items() if category in sections[section] -%}
{%- if category in special_category_admonitions -%}
:::{{- ['{', '}'] | join(special_category_admonitions[category] | lower) -}}
{{- '\n\n' -}}
{% for text, change_note_refs in sections[section][category].items() %}
  {{ text }}
{% endfor %}
{{- '\n' -}}
:::

{{- '\n\n' -}}

{%- else -%}

### {{ definitions[category]['name'] }}

{% for text, change_note_refs in sections[section][category].items() %}

  {%-
    set pr_issue_numbers = change_note_refs
    | map('lower')
    | map('int', default=None)
    | select('integer')
    | map('string')
    | list
  -%}

  {%- set arbitrary_refs = [] -%}
  {%- set commit_refs = [] -%}
  {%- with -%}
    {%- set commit_ref_candidates = change_note_refs | reject('in', pr_issue_numbers) -%}
    {%- for cf in commit_ref_candidates -%}
      {%- if cf | length in (7, 8, 40) and cf | int(default=None, base=16) is not none -%}
        {%- set _ = commit_refs.append(cf) -%}
      {%- else -%}
        {%- set _ = arbitrary_refs.append(cf) -%}
      {%- endif -%}
    {%- endfor -%}
  {%- endwith -%}

- {{ text }}

  {{- '\n\n' -}}

  {%- if pr_issue_numbers %}
  *PRs and issues:* {issue}`{{ pr_issue_numbers | join('`, {issue}`') }}`
  {{- '\n' -}}
  {%- endif -%}

  {%- if commit_refs %}
  *Related commits:* {commit}`{{ commit_refs | join('`, {commit}`') }}`
  {{- '\n' -}}
  {%- endif -%}

  {%- if arbitrary_refs %}
  *Unlinked references:* {{ arbitrary_refs | join(', ') }}
  {{- '\n' -}}
  {%- endif -%}

  {{- '\n' -}}

{% endfor -%}
{%- endif -%}

{% endfor %}
{% else %}
No significant changes.

{% endif %}

{% endfor %}


================================================
FILE: changelog.d/1142.feature.md
================================================
Add usage examples to the ``--help`` output for ``pip-compile`` and
``pip-sync`` commands.

-- by {user}`Dzhud`


================================================
FILE: changelog.d/2318.contrib.md
================================================
`pip-tools` now has a policy regarding LLM-generated contributions, noted in the
contributing documentation -- by {user}`sirosen`.

Thanks to {user}`0cjs`, {user}`gpshead`, {user}`mr-c`, {user}`samdoran`,
{user}`webknjaz`, and everyone else in the broader community who helped us
to craft a policy which is considerate of contributors and protective of the
project and its maintainers.


================================================
FILE: changelog.d/2327.contrib.md
================================================
Started running {pypi}`zizmor` as a part of CI pipelines to improve
security of how we configure GitHub Actions CI/CD
-- by {user}`webknjaz`.


================================================
FILE: changelog.d/2343.contrib.md
================================================
pip-tools docs now support GitHub Flavored Markdown admonition blocks
-- by {user}`webknjaz`.


================================================
FILE: changelog.d/README.md
================================================
# How this folder is managed

<!-- sphinx-inclusion-post-this-line -->

## Adding Change Notes with PRs

It is important to maintain a changelog to explain to users what changed
between versions.

To avoid merge conflicts, we use
[Towncrier](https://towncrier.readthedocs.io/en/stable/) to maintain our
changelog.

Towncrier uses separate files, "news fragments", for each pull request.
On release, those fragments are compiled into the changelog.

You don't need to install Towncrier to contribute, you just have to follow some
simple rules!

- In your pull request, add a new file into `changelog.d/` with a filename
  formatted as `$NUMBER.$CATEGORY.md`.

  - The number is the PR number or issue number which your PR addresses.

  - The category is `bugfix`, `feature`, `deprecation`, `breaking`, `doc`,
    `packaging`, `contrib`, or `misc`. The maintainers may use special
    categories `highlights` and `afterword`, but regular contributors
    don't generally need to.

  - For example, if your PR fixes bug #404, the change notes should be named
    `changelog.d/404.bugfix.md`.

- If multiple issues are addressed, create a symlink to the change notes with
  another issue number in the name.
  Towncrier will automatically merge files into one entry with multiple links.

- Prefer the simple past or constructions with "now".

- Include a byline, `` -- by {user}`github-username` ``

You can preview the changelog by running `tox run -e build-docs` and viewing
the changelog in the docs.

### Categories

The categories for change notes are defined as follows.

- `bugfix`: A fix for something we deemed improper or undesired behavior.

- `feature`: A new behavior, such as a new flag or environment variable.

- `deprecation`: A declaration of future removals and breaking changes in
  behavior.

- `breaking`: A change in behavior which changes or violates established user
  expectations
  (e.g., removing a flag or changing output formatting).

- `doc`: Notable updates to the documentation structure or build process.

- `packaging`: Changes in how `pip-tools` itself is packaged and tested which
  may impact downstreams and redistributors.

- `contrib`: Changes to the contributor experience
  (e.g., running tests, building the docs, or setting up a development
  environment).

- `misc`: Changes that don't fit any of the other categories.

- `highlights`: A prelude to the release notes. Normally filled out by
  the maintainers with important announcements concerning a `pip-tools`
  release. It is rendered before the normal change log categories.

  > [!IMPORTANT]
  > The file name must not reference a number but be orphan, starting
  > with a `+`.

- `afterword`: A concluding paragraph after the release notes. May be
  filled out by the maintainers if they want to include additional
  free-form notes. It is rendered after the normal change log categories.

  > [!IMPORTANT]
  > The file name must not reference a number but be orphan, starting
  > with a `+`.

Sometimes it's not clear which category to use for a change.
Do your best and a maintainer can discuss this with you during review.

### Examples

Example bugfix, [`2223.bugfix.md`]:

```md
Fixed a bug which removed slashes from URLs in `-r` and `-c` in the output
of `pip-compile` -- by {user}`sirosen`.
```

Example contributor update, [`2214.contrib.md`]:

```md
`pip-tools` now tests on and officially supports `pip` version 25.2
-- by {user}`sirosen`.
```

[`2223.bugfix.md`]: https://github.com/jazzband/pip-tools/pull/2224
[`2214.contrib.md`]: https://github.com/jazzband/pip-tools/pull/2214

### Rationale

When making a change to `pip-tools`, it is important to communicate the
differences that end-users will experience in a manner that they can
understand.

Details of the change that are primarily of interest only to `pip-tools`
developers may be irrelevant to most users, and if so, then those details can
be omitted from the change notes.
Then, when the maintainers publish a new release, they'll automatically use
these records to compose a change log for the respective version.

We write change notes in the past tense because this suits the users who will
be reading these notes.
Combined with others, the notes will be a part of the "news digest" telling the
readers what **changed** in a specific version of `pip-tools` since the
previous version.

This methodology has several benefits, including those covered by the
[Towncrier Philosophy](https://towncrier.readthedocs.io/en/stable/#philosophy):

- Change notes separate the user-facing description of changes from the
  implementation details.
  Details go into the git history, but users aren't expected to care about
  them.

- The release engineer may not have been involved in each issue and pull
  request.
  Writing the notes early in the process involves the developers in the best
  position to write good notes.

- Describing a change can help during code review.
  The reviewer can better identify which effects of a change were intentional
  and which were not.


================================================
FILE: docs/.gitignore
================================================
!requirements.in
!requirements.txt


================================================
FILE: docs/changelog.md
================================================
# Changelog

```{eval-rst}

.. MyST doesn't support the "only" directive correctly. It always evaluates to
.. true.
..
.. But if we drop into sphinx eval-rst, it works fine.
.. We then need to include our draft changelog content as markdown.
..
.. We're making a "MyST sandwich", with RST for the `{only}` directive in the
.. middle.
..
.. Using `include` with a `parser` is documented here:
.. https://myst-parser.readthedocs.io/en/latest/faq/index.html#include-rst-files-into-a-markdown-file

.. only:: not is_release

    .. include:: ../changelog.d/.draft_changelog_partial.md
        :parser: myst_parser.sphinx_

```

```{include} ../CHANGELOG.md
:start-after: <!-- towncrier release notes start -->
```


================================================
FILE: docs/cli/index.md
================================================
# Command Line Reference

This page provides a reference for the `pip-tools` command-line interface (CLI):

```{toctree}
:maxdepth: 1

pip-compile
pip-sync
```


================================================
FILE: docs/cli/pip-compile.md
================================================
# pip-compile

```{program-output} pip-compile --help

```


================================================
FILE: docs/cli/pip-sync.md
================================================
# pip-sync

```{program-output} pip-sync --help

```


================================================
FILE: docs/conf.py
================================================
# https://www.sphinx-doc.org/en/master/usage/configuration.html
"""Configuration file for the Sphinx documentation builder."""

from __future__ import annotations

import os
from importlib.metadata import version as get_version
from pathlib import Path

from sphinx.application import Sphinx
from sphinx.util import logging
from sphinx.util.console import bold

logger = logging.getLogger(__name__)

PROJECT_ROOT_DIR = Path(__file__).parents[1].resolve()
IS_RELEASE_ON_RTD = (
    os.getenv("READTHEDOCS", "False") == "True"
    and os.environ["READTHEDOCS_VERSION_TYPE"] == "tag"
)


# -- Project information -----------------------------------------------------

project = "pip-tools"
author = f"{project} Contributors"
copyright = f"The {author}"

# The full version, including alpha/beta/rc tags
release = get_version(project)

# The short X.Y version
version = ".".join(release.split(".")[:3])

logger.info(bold("%s version: %s"), project, version)
logger.info(bold("%s release: %s"), project, release)

# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
    # Stdlib extensions:
    "sphinx.ext.intersphinx",
    # Third-party extensions:
    "click_extra.sphinx",  # provides GitHub-flavored admonition syntax
    "myst_parser",
    "sphinxcontrib.apidoc",
    "sphinxcontrib.programoutput",
    "sphinxcontrib.towncrier.ext",  # provides `.. towncrier-draft-entries::`
    "sphinx_issues",
]

# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
#
html_theme = "furo"
html_title = f"<nobr>{project}</nobr> documentation v{release}"


# -- Options for intersphinx ----------------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#configuration

intersphinx_mapping = {
    "python": ("https://docs.python.org/3", None),
}

issues_github_path = "jazzband/pip-tools"

towncrier_draft_autoversion_mode = "draft"
towncrier_draft_include_empty = True
towncrier_draft_working_directory = PROJECT_ROOT_DIR
towncrier_draft_config_path = "towncrier.toml"  # relative to cwd

# -------------------------------------------------------------------------
default_role = "any"
nitpicky = True

linkcheck_ignore = [
    r"^https://matrix\.to/#",
    r"^https://img.shields.io/matrix",
    r"^https://results\.pre-commit\.ci/latest/github/jazzband/pip-tools/",
    # checking sphinx-issues links to GitHub results in rate limiting errors
    # skip any username validation and pip-tools link checking
    # (this also means we won't get spurious errors when users delete their GitHub accounts)
    r"^https://github\.com/jazzband/pip-tools/(issues|pull|commit)/",
    r"^https://github\.com/sponsors/",
]

nitpick_ignore_regex = [
    ("py:class", "pip.*"),
    ("py:class", "pathlib.*"),
    ("py:class", "click.*"),
    ("py:class", "build.*"),
    ("py:class", "optparse.*"),
    ("py:class", "_ImportLibDist"),
    ("py:class", "PackageMetadata"),
    ("py:class", "importlib.*"),
    ("py:class", "IndexContent"),
    ("py:exc", "click.*"),
]

suppress_warnings = [
    "myst.xref_missing",
    # MyST erroneously flags the draft changelog as having improper header levels
    # because it starts at H2 instead of H1.
    # However, it is written only for inclusion in a broader doc, so the heading
    # levels are actually correct.
    "myst.header",
]

# -- Apidoc options -------------------------------------------------------

apidoc_excluded_paths: list[str] = []
apidoc_extra_args = [
    "--implicit-namespaces",
    "--private",  # include “_private” modules
]
apidoc_module_first = False
apidoc_module_dir = "../piptools"
apidoc_output_dir = "pkg"
apidoc_separate_modules = True
apidoc_toc_file = None


# -- myst_parser options --------------------------------------------------
myst_enable_extensions = {
    "colon_fence",
}


# -- Sphinx extension-API `setup()` hook


def setup(app: Sphinx) -> dict[str, bool | str]:
    """Register project-local Sphinx extension-API customizations.

    :param app: Initialized Sphinx app instance.
    :returns: Extension metadata.
    """
    if IS_RELEASE_ON_RTD:
        app.tags.add("is_release")

    return {
        "parallel_read_safe": True,
        "parallel_write_safe": True,
        "version": release,
    }


================================================
FILE: docs/contributing.md
================================================
# Contributing

```{include} ../CONTRIBUTING.md
:start-after: <!-- sphinx-inclusion-post-this-line -->
```

```{include} ../changelog.d/README.md
:start-after: <!-- sphinx-inclusion-post-this-line -->
```


================================================
FILE: docs/index.md
================================================
<!-- pyml disable-next-line no-trailing-punctuation -->
# Welcome to pip-tools' documentation!

```{include} ../README.md

```

```{toctree}
:hidden:
:maxdepth: 2
:caption: Contents

cli/index
contributing
changelog
```

```{toctree}
:hidden:
:caption: Private API reference

pkg/modules
```


================================================
FILE: docs/pkg/.gitignore
================================================
*
!.gitignore


================================================
FILE: docs/requirements.in
================================================
click-extra [sphinx]  # GitHub-flavored admonitions: https://github.com/executablebooks/MyST-Parser/issues/845#issuecomment-3580549737
furo
myst-parser
setuptools-scm
sphinx
sphinxcontrib-apidoc
sphinxcontrib-programoutput
sphinxcontrib-towncrier
sphinx-issues


================================================
FILE: docs/requirements.txt
================================================
#
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
#    pip-compile --allow-unsafe --output-file=docs/requirements.txt --strip-extras ./pyproject.toml docs/requirements.in
#
accessible-pygments==0.0.5
    # via furo
alabaster==1.0.0
    # via sphinx
babel==2.18.0
    # via sphinx
beautifulsoup4==4.14.3
    # via furo
boltons==25.0.0
    # via click-extra
bracex==2.6
    # via wcmatch
build==1.4.0
    # via pip-tools (pyproject.toml)
certifi==2026.1.4
    # via requests
charset-normalizer==3.4.4
    # via requests
click==8.3.1
    # via
    #   click-extra
    #   cloup
    #   pip-tools (pyproject.toml)
    #   towncrier
click-extra==7.5.3
    # via -r docs/requirements.in
cloup==3.0.8
    # via click-extra
deepmerge==2.0
    # via click-extra
distro==1.9.0
    # via extra-platforms
docutils==0.22.4
    # via
    #   click-extra
    #   myst-parser
    #   sphinx
extra-platforms==8.0.0
    # via click-extra
furo==2025.12.19
    # via -r docs/requirements.in
idna==3.11
    # via requests
imagesize==1.4.1
    # via sphinx
jinja2==3.1.6
    # via
    #   myst-parser
    #   sphinx
    #   towncrier
markdown-it-py==4.0.0
    # via
    #   mdit-py-plugins
    #   myst-parser
markupsafe==3.0.3
    # via jinja2
mdit-py-plugins==0.5.0
    # via myst-parser
mdurl==0.1.2
    # via markdown-it-py
myst-parser==5.0.0
    # via -r docs/requirements.in
packaging==26.0
    # via
    #   build
    #   setuptools-scm
    #   sphinx
    #   wheel
pbr==7.0.3
    # via sphinxcontrib-apidoc
pygments==2.19.2
    # via
    #   accessible-pygments
    #   click-extra
    #   furo
    #   pygments-ansi-color
    #   sphinx
pygments-ansi-color==0.3.0
    # via click-extra
pyproject-hooks==1.2.0
    # via
    #   build
    #   pip-tools (pyproject.toml)
pyyaml==6.0.3
    # via myst-parser
requests==2.32.5
    # via
    #   click-extra
    #   sphinx
roman-numerals==4.1.0
    # via sphinx
setuptools-scm==9.2.2
    # via -r docs/requirements.in
snowballstemmer==3.0.1
    # via sphinx
soupsieve==2.8.3
    # via beautifulsoup4
sphinx==9.1.0
    # via
    #   -r docs/requirements.in
    #   click-extra
    #   furo
    #   myst-parser
    #   sphinx-basic-ng
    #   sphinx-issues
    #   sphinxcontrib-apidoc
    #   sphinxcontrib-programoutput
    #   sphinxcontrib-towncrier
sphinx-basic-ng==1.0.0b2
    # via furo
sphinx-issues==5.0.1
    # via -r docs/requirements.in
sphinxcontrib-apidoc==0.6.0
    # via -r docs/requirements.in
sphinxcontrib-applehelp==2.0.0
    # via sphinx
sphinxcontrib-devhelp==2.0.0
    # via sphinx
sphinxcontrib-htmlhelp==2.1.0
    # via sphinx
sphinxcontrib-jsmath==1.0.1
    # via sphinx
sphinxcontrib-programoutput==0.18
    # via -r docs/requirements.in
sphinxcontrib-qthelp==2.0.0
    # via sphinx
sphinxcontrib-serializinghtml==2.0.0
    # via sphinx
sphinxcontrib-towncrier==0.5.0a0
    # via -r docs/requirements.in
tabulate==0.9.0
    # via click-extra
towncrier==25.8.0
    # via sphinxcontrib-towncrier
typing-extensions==4.15.0
    # via beautifulsoup4
urllib3==2.6.3
    # via requests
wcmatch==10.1
    # via click-extra
wcwidth==0.5.3
    # via tabulate
wheel==0.46.3
    # via pip-tools (pyproject.toml)

# The following packages are considered to be unsafe in a requirements file:
pip==26.0
    # via pip-tools (pyproject.toml)
setuptools==80.10.2
    # via
    #   pbr
    #   pip-tools (pyproject.toml)
    #   setuptools-scm


================================================
FILE: examples/django.in
================================================
# This file includes the Django project, and the debug toolbar
Django<2.2.1   # suppose some version requirement
django-debug-toolbar


================================================
FILE: examples/flask.in
================================================
# Flask has 2nd and 3rd level dependencies
Flask


================================================
FILE: examples/hypothesis.in
================================================
hypothesis[django]


================================================
FILE: examples/protection.in
================================================
# This package depends on setuptools, which should not end up in the compiled
# requirements, because it may cause conflicts with pip itself
python-levenshtein>=0.12.0


================================================
FILE: examples/readme/constraints.txt
================================================
#
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
#    pip-compile --all-build-deps --all-extras --output-file=constraints.txt --strip-extras pyproject.toml
#
asgiref==3.5.2
    # via django
attrs==22.1.0
    # via pytest
django==4.1
    # via my-cool-django-app (pyproject.toml)
editables==0.3
    # via hatchling
hatchling==1.11.1
    # via my-cool-django-app (pyproject.toml::build-system.requires)
iniconfig==1.1.1
    # via pytest
packaging==21.3
    # via
    #   hatchling
    #   pytest
pathspec==0.10.2
    # via hatchling
pluggy==1.0.0
    # via
    #   hatchling
    #   pytest
py==1.11.0
    # via pytest
pyparsing==3.0.9
    # via packaging
pytest==7.1.2
    # via my-cool-django-app (pyproject.toml)
sqlparse==0.4.2
    # via django
tomli==2.0.1
    # via
    #   hatchling
    #   pytest


================================================
FILE: examples/readme/pyproject.toml
================================================
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-cool-django-app"
version = "42"
dependencies = ["django"]

[project.optional-dependencies]
dev = ["pytest"]


================================================
FILE: examples/sentry.in
================================================
# Sentry has a very large dependency tree
sentry


================================================
FILE: piptools/__init__.py
================================================
from __future__ import annotations

import locale

from click import secho

# Needed for locale.getpreferredencoding(False) to work
# in pip._internal.utils.encoding.auto_decode
try:
    locale.setlocale(locale.LC_ALL, "")
except locale.Error as e:  # pragma: no cover
    # setlocale can apparently crash if locale are uninitialized
    secho(f"Ignoring error when setting locale: {e}", fg="red")


================================================
FILE: piptools/__main__.py
================================================
from __future__ import annotations

import click

from piptools.scripts import compile, sync


@click.group()
def cli() -> None:
    pass


cli.add_command(compile.cli, "compile")
cli.add_command(sync.cli, "sync")


# Enable ``python -m piptools ...``.
if __name__ == "__main__":
    cli()


================================================
FILE: piptools/_compat/__init__.py
================================================
from __future__ import annotations

from .pip_compat import (
    Distribution,
    canonicalize_name,
    create_wheel_cache,
    get_dev_pkgs,
    parse_requirements,
)

__all__ = [
    "Distribution",
    "parse_requirements",
    "create_wheel_cache",
    "get_dev_pkgs",
    "canonicalize_name",
]


================================================
FILE: piptools/_compat/_tomllib_compat.py
================================================
from __future__ import annotations

import sys

if sys.version_info >= (3, 11):
    from tomllib import TOMLDecodeError, load, loads
else:
    from tomli import TOMLDecodeError, load, loads


__all__ = ["TOMLDecodeError", "load", "loads"]


================================================
FILE: piptools/_compat/path_compat.py
================================================
"""
Compatibility helpers for working with paths and :mod:`pathlib` across platforms
and Python versions.
"""

from __future__ import annotations

import os.path
import pathlib
import sys

__all__ = ("relative_to_walk_up",)


def relative_to_walk_up(path: pathlib.Path, start: pathlib.Path) -> pathlib.Path:
    """
    Compute a relative path allowing for the input to not be a subpath of the start.

    This is a compatibility helper for ``pathlib.Path.relative_to(..., walk_up=True)``
    on all Python versions. (``walk_up: bool`` is Python 3.12+)
    """
    # prefer `pathlib.Path.relative_to` where available
    if sys.version_info >= (3, 12):
        return path.relative_to(start, walk_up=True)

    str_result = os.path.relpath(path, start=start)
    return pathlib.Path(str_result)


================================================
FILE: piptools/_compat/pip_compat.py
================================================
from __future__ import annotations

import optparse
import pathlib
import typing as _t
import urllib.parse
from collections.abc import Iterable, Iterator
from dataclasses import dataclass

from pip._internal.cache import WheelCache
from pip._internal.index.package_finder import PackageFinder
from pip._internal.metadata import BaseDistribution
from pip._internal.metadata.pkg_resources import Distribution as _PkgResourcesDist
from pip._internal.models.direct_url import DirectUrl
from pip._internal.models.link import Link
from pip._internal.network.session import PipSession
from pip._internal.req import InstallRequirement
from pip._internal.req import parse_requirements as _parse_requirements
from pip._internal.req.constructors import install_req_from_parsed_requirement
from pip._vendor.pkg_resources import Requirement

from .path_compat import relative_to_walk_up

# The Distribution interface has changed between pkg_resources and
# importlib.metadata, so this compat layer allows for a consistent access
# pattern. In pip 22.1, importlib.metadata became the default on Python 3.11
# (and later), but is overridable. `select_backend` returns what's being used.
# Secondly, the canonicalize_name function received typing improvements
# in pip 21.2, since mypy runs on an older version, this compat layer ensures correct
# typing regardless of the pip version used. NormalizedName and str are interchangeable.
if _t.TYPE_CHECKING:
    from pip._internal.metadata.importlib import Distribution as _ImportLibDist

    def canonicalize_name(name: str) -> str: ...

else:
    from pip._vendor.packaging.utils import canonicalize_name  # noqa: F401

from .._internal import _pip_api


@dataclass(frozen=True)
class Distribution:
    key: str
    version: str
    requires: Iterable[Requirement]
    direct_url: DirectUrl | None

    @classmethod
    def from_pip_distribution(cls, dist: BaseDistribution) -> Distribution:
        # TODO: Use only the BaseDistribution protocol properties and methods
        # instead of specializing by type.
        if isinstance(dist, _PkgResourcesDist):
            return cls._from_pkg_resources(dist)
        else:
            return cls._from_importlib(dist)

    @classmethod
    def _from_pkg_resources(cls, dist: _PkgResourcesDist) -> Distribution:
        return cls(
            dist._dist.key, dist._dist.version, dist._dist.requires(), dist.direct_url
        )

    @classmethod
    def _from_importlib(cls, dist: _ImportLibDist) -> Distribution:
        """Mimic pkg_resources.Distribution.requires for the case of no
        extras.

        This doesn't fulfill that API's ``extras`` parameter but
        satisfies the needs of pip-tools.
        """
        reqs = (Requirement.parse(req) for req in (dist._dist.requires or ()))
        requires = [
            req
            for req in reqs
            if not req.marker or req.marker.evaluate({"extra": None})
        ]
        return cls(dist._dist.name, dist._dist.version, requires, dist.direct_url)


class FileLink(Link):  # type: ignore[misc]
    """Wrapper for ``pip``'s ``Link`` class."""

    _url: str

    @property
    def file_path(self) -> str:
        # overriding the actual property to bypass some validation
        return self._url


def parse_requirements(
    filename: str,
    session: PipSession,
    finder: PackageFinder | None = None,
    options: optparse.Values | None = None,
    constraint: bool = False,
    isolated: bool = False,
    comes_from_stdin: bool = False,
) -> Iterator[InstallRequirement]:
    # the `comes_from` data will be rewritten in different ways in different conditions
    # each rewrite rule is expressible as a str->str function
    rewrite_comes_from: _t.Callable[[str], str]

    if comes_from_stdin:
        # if data is coming from stdin, then `comes_from="-r -"`
        rewrite_comes_from = _rewrite_comes_from_to_hardcoded_stdin_value
    elif pathlib.Path(filename).is_absolute():
        # if the input path is absolute, just normalize paths to posix-style
        rewrite_comes_from = _normalize_comes_from_location
    else:
        # if the input was a relative path, set the rewrite rule to rewrite
        # absolute paths to be relative
        rewrite_comes_from = _relativize_comes_from_location

    for parsed_req in _parse_requirements(
        filename, session, finder=finder, options=options, constraint=constraint
    ):
        install_req = install_req_from_parsed_requirement(parsed_req, isolated=isolated)
        if install_req.editable and not parsed_req.requirement.startswith("file://"):
            # ``Link.url`` is what is saved to the output file
            # we set the url directly to undo the transformation in pip's Link class
            file_link = FileLink(install_req.link.url)
            file_link._url = parsed_req.requirement
            install_req.link = file_link
        install_req = _pip_api.copy_install_requirement(install_req)

        install_req.comes_from = rewrite_comes_from(install_req.comes_from)

        yield install_req


def _rewrite_comes_from_to_hardcoded_stdin_value(_: str, /) -> str:
    """Produce the hardcoded ``comes_from`` value for stdin."""
    return "-r -"


def _relativize_comes_from_location(original_comes_from: str, /) -> str:
    """
    Convert a ``comes_from`` path to a relative posix path.

    This is the rewrite rule used when ``-r`` or ``-c`` appears in
    ``comes_from`` data with an absolute path.

    The ``-r`` or ``-c`` qualifier is retained, the path is relativized
    with respect to the CWD, and the path is converted to posix style.
    """
    # require `-r` or `-c` as the source
    if not original_comes_from.startswith(("-r ", "-c ")):
        return original_comes_from

    # split on the space
    prefix, space_sep, suffix = original_comes_from.partition(" ")

    # if the value part is a remote URI for pip, return the original
    if _is_remote_pip_uri(suffix):
        return original_comes_from

    file_path = pathlib.Path(suffix)

    # if the path was not absolute, normalize to posix-style and finish processing
    if not file_path.is_absolute():
        return f"{prefix} {file_path.as_posix()}"

    # make it relative to the current working dir
    suffix = relative_to_walk_up(file_path, pathlib.Path.cwd()).as_posix()
    return f"{prefix}{space_sep}{suffix}"


def _normalize_comes_from_location(original_comes_from: str, /) -> str:
    """
    Convert a ``comes_from`` path to a posix-style path.

    This is the rewrite rule when ``-r`` or ``-c`` appears in ``comes_from``
    data and the input path was absolute, meaning we should not relativize the
    locations.

    The ``-r`` or ``-c`` qualifier is retained, and the path is converted to
    posix style.
    """
    # require `-r` or `-c` as the source
    if not original_comes_from.startswith(("-r ", "-c ")):
        return original_comes_from

    # split on the space
    prefix, space_sep, suffix = original_comes_from.partition(" ")

    # if the value part is a remote URI for pip, return the original
    if _is_remote_pip_uri(suffix):
        return original_comes_from

    # convert to a posix-style path
    suffix = pathlib.Path(suffix).as_posix()
    return f"{prefix}{space_sep}{suffix}"


def _is_remote_pip_uri(value: str) -> bool:
    """
    Test a string to see if it is a URI treated as a remote file in ``pip``.
    Specifically this means that it's a 'file', 'http', or 'https' URI.

    The test is performed by trying a URL parse and reading the scheme.
    """
    scheme = urllib.parse.urlsplit(value).scheme
    return scheme in {"file", "http", "https"}


def create_wheel_cache(cache_dir: str, format_control: str | None = None) -> WheelCache:
    kwargs: dict[str, str | None] = {"cache_dir": cache_dir}
    if _pip_api.PIP_VERSION_MAJOR_MINOR <= (23, 0):
        kwargs["format_control"] = format_control
    return WheelCache(**kwargs)


def get_dev_pkgs() -> set[str]:
    if _pip_api.PIP_VERSION_MAJOR_MINOR <= (23, 1):
        from pip._internal.commands.freeze import DEV_PKGS

        return _t.cast(set[str], DEV_PKGS)

    from pip._internal.commands.freeze import _dev_pkgs

    return _t.cast(set[str], _dev_pkgs())


================================================
FILE: piptools/_compat/tempfile_compat.py
================================================
"""
Compatibility helpers for :mod:`tempfile` usage across platforms
and python versions.
"""

from __future__ import annotations

import collections.abc as _c
import contextlib
import os
import tempfile
import typing as _t

__all__ = ("named_temp_file",)


@contextlib.contextmanager
def named_temp_file(mode: str = "wt") -> _c.Iterator[_t.IO[str]]:
    """
    A safe wrapper over NamedTemporaryFile for usage on Windows as well as
    POSIX systems.

    The issue we have is that we cannot guarantee that ``pip`` will open temporary
    files on Windows with ``O_TEMPORARY`` when passed the path, resulting in surprising
    behavior.
    """
    temp_file = tempfile.NamedTemporaryFile(mode=mode, delete=False)
    try:
        yield temp_file
    finally:
        temp_file.close()
        os.unlink(temp_file.name)


================================================
FILE: piptools/_internal/__init__.py
================================================


================================================
FILE: piptools/_internal/_pip_api/__init__.py
================================================
"""
The ``piptools._pip_api`` subpackage defines an API layer on top of ``pip`` internals
and usage. It is a private API for the rest of ``piptools`` to leverage.
"""

from __future__ import annotations

from .cli_options import postprocess_cli_options
from .install_requirements import (
    copy_install_requirement,
    create_install_requirement,
    create_install_requirement_from_line,
)
from .package_finder import (
    finder_allows_all_prereleases,
    finder_allows_prereleases_of_req,
)
from .pip_version import (
    PIP_VERSION,
    PIP_VERSION_MAJOR_MINOR,
    PIP_VERSION_TUPLE,
    get_pip_version_for_python_executable,
)

__all__ = (
    "PIP_VERSION",
    "PIP_VERSION_MAJOR_MINOR",
    "PIP_VERSION_TUPLE",
    "get_pip_version_for_python_executable",
    "create_install_requirement",
    "create_install_requirement_from_line",
    "copy_install_requirement",
    "finder_allows_all_prereleases",
    "finder_allows_prereleases_of_req",
    "postprocess_cli_options",
)


================================================
FILE: piptools/_internal/_pip_api/cli_options.py
================================================
"""
Tools for parsing pip CLI options.
"""

from __future__ import annotations

import optparse

from pip._internal.cli import cmdoptions

from . import pip_version as _pip_version


def postprocess_cli_options(options: optparse.Values) -> None:
    """
    After CLI parsing, pip processes options further to check various constraints and
    coalesce values. Emulate and/or invoke those same behaviors.
    """
    if _pip_version.PIP_VERSION_MAJOR_MINOR >= (26, 0):
        cmdoptions.check_release_control_exclusive(options)


================================================
FILE: piptools/_internal/_pip_api/install_requirements.py
================================================
from __future__ import annotations

import copy
import typing as _t

from pip._internal.req import InstallRequirement
from pip._internal.req.constructors import install_req_from_line
from pip._vendor.packaging.utils import canonicalize_name
from pip._vendor.packaging.version import Version

from . import pip_version as _pip_version


def create_install_requirement(
    name: str, version: str | Version, ireq: InstallRequirement
) -> InstallRequirement:
    # If no extras are specified, the extras string is blank
    extras_string = ""
    extras = ireq.extras
    if extras:
        # Sort extras for stability
        extras_string = f"[{','.join(sorted(extras))}]"

    version_pin_operator = "=="
    version_as_str = str(version)
    for specifier in ireq.specifier:
        if specifier.operator == "===" and specifier.version == version_as_str:
            version_pin_operator = "==="
            break

    return create_install_requirement_from_line(
        str(f"{name}{extras_string}{version_pin_operator}{version}"),
        constraint=ireq.constraint,
    )


def create_install_requirement_from_line(
    *args: _t.Any, **kwargs: _t.Any
) -> InstallRequirement:
    return copy_install_requirement(install_req_from_line(*args, **kwargs))


def copy_install_requirement(
    template: InstallRequirement, **extra_kwargs: _t.Any
) -> InstallRequirement:
    """Make a copy of a template ``InstallRequirement`` with extra kwargs."""
    # Prepare install requirement kwargs.
    kwargs = {
        "comes_from": template.comes_from,
        "editable": template.editable,
        "link": template.link,
        "markers": template.markers,
        "isolated": template.isolated,
        "hash_options": template.hash_options,
        "constraint": template.constraint,
        "extras": template.extras,
        "user_supplied": template.user_supplied,
    }
    if _pip_version.PIP_VERSION_MAJOR_MINOR < (25, 3):  # pragma: <3.9 cover
        # Ref: https://github.com/jazzband/pip-tools/issues/2252
        kwargs["use_pep517"] = template.use_pep517
        kwargs["global_options"] = template.global_options
    kwargs.update(extra_kwargs)

    if _pip_version.PIP_VERSION_MAJOR_MINOR >= (25, 3):  # pragma: >=3.9 cover
        # Ref: https://github.com/jazzband/pip-tools/issues/2252
        kwargs.pop("use_pep517", None)
        kwargs.pop("global_options", None)

    if _pip_version.PIP_VERSION_MAJOR_MINOR <= (23, 0):
        kwargs["install_options"] = template.install_options

    # Original link does not belong to install requirements constructor,
    # pop it now to update later.
    original_link = kwargs.pop("original_link", None)

    # Copy template.req if not specified in extra kwargs.
    if "req" not in kwargs:
        kwargs["req"] = copy.deepcopy(template.req)

    kwargs["extras"] = set(map(canonicalize_name, kwargs["extras"]))
    if kwargs["req"]:
        kwargs["req"].extras = set(kwargs["extras"])

    ireq = InstallRequirement(**kwargs)

    # If the original_link was None, keep it so. Passing `link` as an
    # argument to `InstallRequirement` sets it as the original_link.
    ireq.original_link = (
        template.original_link if original_link is None else original_link
    )

    return ireq


================================================
FILE: piptools/_internal/_pip_api/package_finder.py
================================================
"""
PackageFinder interfaces for pip-tools.

Because the PackageFinder class itself has evolved over pip's lifetime, these helpers
provide compatible interfaces which wrap methods and attributes.
"""

from __future__ import annotations

from pip._internal.index.package_finder import PackageFinder
from pip._internal.req import InstallRequirement

from . import pip_version as _pip_version


def finder_allows_prereleases_of_req(
    finder: PackageFinder, ireq: InstallRequirement
) -> bool:
    """
    Check if a package finder will get prereleases for a given requirement.

    On older pip versions, this is not specific to the requirement, but on newer ones it
    is.
    """
    if _pip_version.PIP_VERSION_MAJOR_MINOR < (26, 0):
        return finder.allow_all_prereleases  # type: ignore[no-any-return]
    else:
        return finder.release_control.allows_prereleases(  # type: ignore[no-any-return]
            ireq.req.name
        )


def finder_allows_all_prereleases(finder: PackageFinder) -> bool:
    """
    Check if a package finder will get prereleases for all requirements.

    On older pip versions, this is not specific to the requirement, but on newer ones it
    is. However, ``--pre`` is translated internally to ``":all:"`` on those versions.
    """
    if _pip_version.PIP_VERSION_MAJOR_MINOR < (26, 0):
        return bool(finder.allow_all_prereleases)
    else:
        return ":all:" in finder.release_control.all_releases


================================================
FILE: piptools/_internal/_pip_api/pip_version.py
================================================
from __future__ import annotations

import pip
from pip._vendor.packaging.version import Version
from pip._vendor.packaging.version import parse as parse_version

from .. import _subprocess

PIP_VERSION = parse_version(pip.__version__)
PIP_VERSION_TUPLE: tuple[int, ...] = tuple(
    map(int, PIP_VERSION.base_version.split("."))
)
PIP_VERSION_MAJOR_MINOR: tuple[int, int] = PIP_VERSION_TUPLE[:2]  # type: ignore[assignment]


def get_pip_version_for_python_executable(python_executable: str) -> Version:
    """Return pip version for the given python executable."""

    str_version = _subprocess.run_python_snippet(
        python_executable, "import pip; print(pip.__version__)"
    )
    return Version(str_version)


================================================
FILE: piptools/_internal/_subprocess.py
================================================
# WARNING! BE CAREFUL UPDATING THIS FILE
# Consider possible security implications associated with subprocess module.
from __future__ import annotations

import subprocess  # nosec


def run_python_snippet(python_executable: str, code_to_run: str) -> str:
    """
    Execute Python code by calling ``python_executable`` with '-c' option.
    """
    py_exec_cmd = python_executable, "-c", code_to_run

    # subprocess module should never be used with untrusted input
    return subprocess.check_output(  # nosec
        py_exec_cmd,
        shell=False,
        text=True,
    )


================================================
FILE: piptools/build.py
================================================
from __future__ import annotations

import collections
import contextlib
import os
import pathlib
import sys
import tempfile
import typing as _t
from collections.abc import Iterator
from dataclasses import dataclass
from importlib import metadata as importlib_metadata

import build
import build.env
import pyproject_hooks
from pip._internal.req import InstallRequirement
from pip._internal.req.constructors import parse_req_from_line
from pip._vendor.packaging.markers import Marker
from pip._vendor.packaging.requirements import Requirement

from ._compat import _tomllib_compat
from ._internal import _pip_api

PYPROJECT_TOML = "pyproject.toml"

_T = _t.TypeVar("_T")


if sys.version_info >= (3, 10):
    from importlib.metadata import PackageMetadata
else:

    class PackageMetadata(_t.Protocol):
        @_t.overload
        def get_all(self, name: str, failobj: None = None) -> list[_t.Any] | None: ...

        @_t.overload
        def get_all(self, name: str, failobj: _T) -> list[_t.Any] | _T: ...


@dataclass
class StaticProjectMetadata:
    extras: tuple[str, ...]
    requirements: tuple[InstallRequirement, ...]


@dataclass
class ProjectMetadata:
    extras: tuple[str, ...]
    requirements: tuple[InstallRequirement, ...]
    build_requirements: tuple[InstallRequirement, ...]


def maybe_statically_parse_project_metadata(
    src_file: pathlib.Path,
) -> StaticProjectMetadata | None:
    """
    Return the metadata for a project, if it can be statically parsed from ``pyproject.toml``.

    This function is typically significantly faster than invoking a build backend.
    Returns None if the project metadata cannot be statically parsed.
    """
    if src_file.name != PYPROJECT_TOML:
        return None

    try:
        with open(src_file, "rb") as f:
            pyproject_contents = _tomllib_compat.load(f)
    except _tomllib_compat.TOMLDecodeError:
        return None

    # Not valid PEP 621 metadata
    if (
        "project" not in pyproject_contents
        or "name" not in pyproject_contents["project"]
    ):
        return None

    project_table = pyproject_contents["project"]

    # Dynamic dependencies require build backend invocation
    dynamic = project_table.get("dynamic", [])
    if "dependencies" in dynamic or "optional-dependencies" in dynamic:
        return None

    package_name = project_table["name"]
    comes_from = f"{package_name} ({src_file.as_posix()})"

    extras = project_table.get("optional-dependencies", {}).keys()
    install_requirements = [
        InstallRequirement(Requirement(req), comes_from)
        for req in project_table.get("dependencies", [])
    ]
    for extra, reqs in (
        pyproject_contents.get("project", {}).get("optional-dependencies", {}).items()
    ):
        for req in reqs:
            requirement = Requirement(req)
            if requirement.name == package_name:
                # Similar to logic for handling self-referential requirements
                # from _prepare_requirements
                requirement.url = src_file.parent.absolute().as_uri()

            # Note we don't need to modify `requirement` to include this extra
            marker = Marker(f"extra == '{extra}'")
            install_requirements.append(
                InstallRequirement(requirement, comes_from, markers=marker)
            )

    return StaticProjectMetadata(
        extras=tuple(extras),
        requirements=tuple(install_requirements),
    )


def build_project_metadata(
    src_file: pathlib.Path,
    build_targets: tuple[str, ...],
    *,
    upgrade_packages: tuple[str, ...] | None = None,
    attempt_static_parse: bool,
    isolated: bool,
    quiet: bool,
) -> ProjectMetadata | StaticProjectMetadata:
    """
    Return the metadata for a project.

    First, optionally attempt to determine the metadata statically from the
    ``pyproject.toml`` file. This will not work if build_targets are specified,
    since we cannot determine build requirements statically.

    Uses the ``prepare_metadata_for_build_wheel`` hook for the wheel metadata
    if available, otherwise ``build_wheel``.

    Uses the ``prepare_metadata_for_build_{target}`` hook for each ``build_targets``
    if available.

    :param src_file: Project source file
    :param build_targets: A tuple of build targets to get the dependencies
                                of (``sdist`` or ``wheel`` or ``editable``).
    :param attempt_static_parse: Whether to attempt to statically parse the
                                 project metadata from ``pyproject.toml``.
                                 Cannot be used with ``build_targets``.
    :param isolated: Whether to run invoke the backend in the current
                     environment or to create an isolated one and invoke it
                     there.
    :param quiet: Whether to suppress the output of subprocesses.
    """

    if attempt_static_parse:
        if build_targets:
            raise ValueError(
                "Cannot execute the PEP 517 optional get_requires_for_build* "
                "hooks statically, as build requirements are requested"
            )
        project_metadata = maybe_statically_parse_project_metadata(src_file)
        if project_metadata is not None:
            return project_metadata

    src_dir = src_file.parent
    with _create_project_builder(
        src_dir,
        upgrade_packages=upgrade_packages,
        isolated=isolated,
        quiet=quiet,
    ) as builder:
        metadata = _build_project_wheel_metadata(builder)
        extras = tuple(metadata.get_all("Provides-Extra") or ())
        requirements = tuple(
            _prepare_requirements(metadata=metadata, src_file=src_file)
        )
        build_requirements = tuple(
            _prepare_build_requirements(
                builder=builder,
                src_file=src_file,
                build_targets=build_targets,
                package_name=_get_name(metadata),
            )
        )
        return ProjectMetadata(
            extras=extras,
            requirements=requirements,
            build_requirements=build_requirements,
        )


@contextlib.contextmanager
def _env_var(
    env_var_name: str,
    env_var_value: str,
    /,
) -> Iterator[None]:
    sentinel = object()
    original_pip_constraint = os.getenv(env_var_name, sentinel)
    pip_constraint_was_unset = original_pip_constraint is sentinel

    os.environ[env_var_name] = env_var_value
    try:
        yield
    finally:
        if pip_constraint_was_unset:
            del os.environ[env_var_name]
        else:
            # Assert here is necessary because MyPy can't infer type
            # narrowing in the complex case.
            assert isinstance(original_pip_constraint, str)
            os.environ[env_var_name] = original_pip_constraint


@contextlib.contextmanager
def _temporary_constraints_file_set_for_pip(
    upgrade_packages: tuple[str, ...],
) -> Iterator[None]:
    with tempfile.NamedTemporaryFile(
        mode="w+t",
        delete=False,  # FIXME: switch to `delete_on_close` in Python 3.12+
    ) as tmpfile:
        # NOTE: `delete_on_close=False` here (or rather `delete=False`,
        # NOTE: temporarily) is important for cross-platform execution. It is
        # NOTE: required on Windows so that the underlying `pip install`
        # NOTE: invocation by pypa/build will be able to access the constraint
        # NOTE: file via a subprocess and not fail installing it due to a
        # NOTE: permission error related to this file handle still open in our
        # NOTE: parent process. To achieve this, we `.close()` the file
        # NOTE: descriptor before we hand off the control to the build frontend
        # NOTE: and with `delete_on_close=False`, the
        # NOTE: `tempfile.NamedTemporaryFile()` context manager does not remove
        # NOTE: it from disk right away.
        # NOTE: Due to support of versions below Python 3.12, we are forced to
        # NOTE: temporarily resort to using `delete=False`, meaning that the CM
        # NOTE: never attempts removing the file from disk, not even on exit.
        # NOTE: So we do this manually until we can migrate to using the more
        # NOTE: ergonomic argument `delete_on_close=False`.

        # Write packages to upgrade to a temporary file to set as
        # constraints for the installation to the builder environment,
        # in case build requirements are among them
        tmpfile.write("\n".join(upgrade_packages))

        # FIXME: replace `delete` with `delete_on_close` in Python 3.12+
        # FIXME: and replace `.close()` with `.flush()`
        tmpfile.close()

        try:
            with _env_var("PIP_CONSTRAINT", tmpfile.name):
                yield
        finally:
            # FIXME: replace `delete` with `delete_on_close` in Python 3.12+
            # FIXME: and drop this manual deletion
            os.unlink(tmpfile.name)


@contextlib.contextmanager
def _create_project_builder(
    src_dir: pathlib.Path,
    *,
    upgrade_packages: tuple[str, ...] | None = None,
    isolated: bool,
    quiet: bool,
) -> Iterator[build.ProjectBuilder]:
    if quiet:
        runner = pyproject_hooks.quiet_subprocess_runner
    else:
        runner = pyproject_hooks.default_subprocess_runner

    if not isolated:
        yield build.ProjectBuilder(src_dir, runner=runner)
        return

    maybe_pip_constrained_context = (
        contextlib.nullcontext()
        if upgrade_packages is None
        else _temporary_constraints_file_set_for_pip(upgrade_packages)
    )

    with maybe_pip_constrained_context, build.env.DefaultIsolatedEnv() as env:
        builder = build.ProjectBuilder.from_isolated_env(env, src_dir, runner)
        env.install(builder.build_system_requires)
        env.install(builder.get_requires_for_build("wheel"))
        yield builder


def _build_project_wheel_metadata(
    builder: build.ProjectBuilder,
) -> PackageMetadata:
    with tempfile.TemporaryDirectory() as tmpdir:
        path = pathlib.Path(builder.metadata_path(tmpdir))
        return importlib_metadata.PathDistribution(path).metadata


def _get_name(metadata: PackageMetadata) -> str:
    retval = metadata.get_all("Name")[0]  # type: ignore[index]
    assert isinstance(retval, str)
    return retval


def _prepare_requirements(
    metadata: PackageMetadata, src_file: pathlib.Path
) -> Iterator[InstallRequirement]:
    package_name = _get_name(metadata)
    comes_from = f"{package_name} ({src_file.as_posix()})"
    package_dir = src_file.parent

    for req in metadata.get_all("Requires-Dist") or []:
        parts = parse_req_from_line(req, comes_from)
        if parts.requirement.name == package_name:
            # Replace package name with package directory in the requirement
            # string so that pip can find the package as self-referential.
            # Note the string can contain extras, so we need to replace only
            # the package name, not the whole string.
            replaced_package_name = req.replace(package_name, str(package_dir), 1)
            parts = parse_req_from_line(replaced_package_name, comes_from)

        yield _pip_api.copy_install_requirement(
            InstallRequirement(
                parts.requirement,
                comes_from,
                link=parts.link,
                markers=parts.markers,
                extras=parts.extras,
            )
        )


def _prepare_build_requirements(
    builder: build.ProjectBuilder,
    src_file: pathlib.Path,
    build_targets: tuple[str, ...],
    package_name: str,
) -> Iterator[InstallRequirement]:
    result = collections.defaultdict(set)

    # Build requirements will only be present if a pyproject.toml file exists,
    # but if there is also a setup.py file then only that will be explicitly
    # processed due to the order of `DEFAULT_REQUIREMENTS_FILES`.
    src_file = src_file.parent / PYPROJECT_TOML

    for req in builder.build_system_requires:
        result[req].add(f"{package_name} ({src_file}::build-system.requires)")
    for build_target in build_targets:
        for req in builder.get_requires_for_build(build_target):
            result[req].add(
                f"{package_name} ({src_file}::build-system.backend::{build_target})"
            )

    for req, comes_from_sources in result.items():
        for comes_from in comes_from_sources:
            yield _pip_api.create_install_requirement_from_line(
                req, comes_from=comes_from
            )


================================================
FILE: piptools/cache.py
================================================
from __future__ import annotations

import json
import os
import platform
import sys
import typing as _t
from collections.abc import Iterable

from pip._internal.req import InstallRequirement
from pip._vendor.packaging.requirements import Requirement

from .exceptions import PipToolsError
from .utils import as_tuple, key_from_req, lookup_table_from_tuples

CacheKey = tuple[str, str]
CacheLookup = dict[str, list[str]]
CacheDict = dict[str, CacheLookup]

_PEP425_PY_TAGS = {"cpython": "cp", "pypy": "pp", "ironpython": "ip", "jython": "jy"}


def _implementation_name() -> str:
    """
    Get Python implementation and version.

    Similar to PEP 425, however the minor version is separated from the major to
    differentiate "3.10" and "31.0".
    """
    implementation_name = platform.python_implementation().lower()
    implementation = _PEP425_PY_TAGS.get(implementation_name, "??")
    return "{}{}.{}".format(implementation, *sys.version_info)


class CorruptCacheError(PipToolsError):
    def __init__(self, path: str):
        self.path = path

    def __str__(self) -> str:
        lines = [
            "The dependency cache seems to have been corrupted.",
            "Inspect, or delete, the following file:",
            f"  {self.path}",
        ]
        return os.linesep.join(lines)


def read_cache_file(cache_file_path: str) -> CacheDict:
    with open(cache_file_path, encoding="utf-8") as cache_file:
        try:
            doc = json.load(cache_file)
        except (json.JSONDecodeError, UnicodeDecodeError):
            raise CorruptCacheError(cache_file_path)

        # Check version and load the contents
        if doc["__format__"] != 1:
            raise ValueError("Unknown cache file format")
        return _t.cast(CacheDict, doc["dependencies"])


class DependencyCache:
    """
    Create new persistent dependency cache for the current Python version.

    The cache file is written to the appropriate user cache dir for the
    current platform, i.e.

        ~/.cache/pip-tools/depcache-pyX.Y.json

    Where py indicates the Python implementation.
    Where X.Y indicates the Python version.
    """

    def __init__(self, cache_dir: str):
        os.makedirs(cache_dir, exist_ok=True)
        cache_filename = f"depcache-{_implementation_name()}.json"

        self._cache_file = os.path.join(cache_dir, cache_filename)
        self._cache: CacheDict | None = None

    @property
    def cache(self) -> CacheDict:
        """
        The dictionary that is the actual in-memory cache.  This property
        lazily loads the cache from disk.
        """
        if self._cache is None:
            try:
                self._cache = read_cache_file(self._cache_file)
            except FileNotFoundError:
                self._cache = {}
        return self._cache

    def as_cache_key(self, ireq: InstallRequirement) -> CacheKey:
        """
        Given a requirement, return its cache key.

        This behavior is a little weird
        in order to allow backwards compatibility with cache files. For a requirement
        without extras, this will return, for example:

        ("ipython", "2.1.0")

        For a requirement with extras, the extras will be comma-separated and appended
        to the version, inside brackets, like so:

        ("ipython", "2.1.0[nbconvert,notebook]")
        """
        name, version, extras = as_tuple(ireq)
        if not extras:
            extras_string = ""
        else:
            extras_string = f"[{','.join(extras)}]"
        return name, f"{version}{extras_string}"

    def write_cache(self) -> None:
        """Write the cache to disk as JSON."""
        doc = {"__format__": 1, "dependencies": self._cache}
        with open(self._cache_file, "w", encoding="utf-8") as f:
            json.dump(doc, f, sort_keys=True)

    def clear(self) -> None:
        self._cache = {}
        self.write_cache()

    def __contains__(self, ireq: InstallRequirement) -> bool:
        pkgname, pkgversion_and_extras = self.as_cache_key(ireq)
        return pkgversion_and_extras in self.cache.get(pkgname, {})

    def __getitem__(self, ireq: InstallRequirement) -> list[str]:
        pkgname, pkgversion_and_extras = self.as_cache_key(ireq)
        return self.cache[pkgname][pkgversion_and_extras]

    def __setitem__(self, ireq: InstallRequirement, values: list[str]) -> None:
        pkgname, pkgversion_and_extras = self.as_cache_key(ireq)
        self.cache.setdefault(pkgname, {})
        self.cache[pkgname][pkgversion_and_extras] = values
        self.write_cache()

    def reverse_dependencies(
        self, ireqs: Iterable[InstallRequirement]
    ) -> dict[str, set[str]]:
        """
        Return a lookup table of reverse dependencies for all the given ireqs.

        Since this is all static, it only works if the dependency cache
        contains the complete data, otherwise you end up with a partial view.
        This is typically no problem if you use this function after the entire
        dependency tree is resolved.
        """
        ireqs_as_cache_values = [self.as_cache_key(ireq) for ireq in ireqs]
        return self._reverse_dependencies(ireqs_as_cache_values)

    def _reverse_dependencies(
        self, cache_keys: Iterable[tuple[str, str]]
    ) -> dict[str, set[str]]:
        """
        Return a lookup table of reverse dependencies for all the given cache keys.

        Example input:

            [('pep8', '1.5.7'),
             ('flake8', '2.4.0'),
             ('mccabe', '0.3'),
             ('pyflakes', '0.8.1')]

        Example output:

            {'pep8': ['flake8'],
             'flake8': [],
             'mccabe': ['flake8'],
             'pyflakes': ['flake8']}

        """
        # First, collect all the dependencies into a sequence of (parent, child)
        # tuples, like [('flake8', 'pep8'), ('flake8', 'mccabe'), ...]
        return lookup_table_from_tuples(
            (key_from_req(Requirement(dep_name)), name)
            for name, version_and_extras in cache_keys
            for dep_name in self.cache[name][version_and_extras]
        )


================================================
FILE: piptools/exceptions.py
================================================
from __future__ import annotations

import operator
from collections.abc import Iterable

from pip._internal.index.package_finder import PackageFinder
from pip._internal.models.candidate import InstallationCandidate
from pip._internal.req import InstallRequirement
from pip._internal.utils.misc import redact_auth_from_url

from ._internal import _pip_api


class PipToolsError(Exception):
    pass


class NoCandidateFound(PipToolsError):
    def __init__(
        self,
        ireq: InstallRequirement,
        candidates_tried: Iterable[InstallationCandidate],
        finder: PackageFinder,
    ) -> None:
        self.ireq = ireq
        self.candidates_tried = candidates_tried
        self.finder = finder

    def __str__(self) -> str:
        versions = []
        pre_versions = []

        for candidate in sorted(
            self.candidates_tried, key=operator.attrgetter("version")
        ):
            version = str(candidate.version)
            if candidate.version.is_prerelease:
                pre_versions.append(version)
            else:
                versions.append(version)

        lines = [f"Could not find a version that matches {self.ireq}"]

        if versions:
            lines.append(f"Tried: {', '.join(versions)}")

        if pre_versions:
            if _pip_api.finder_allows_prereleases_of_req(self.finder, self.ireq):
                line = "Tried"
            else:
                line = "Skipped"

            line += f" pre-versions: {', '.join(pre_versions)}"
            lines.append(line)

        if versions or pre_versions:
            lines.append(
                "There are incompatible versions in the resolved dependencies:"
            )
            source_ireqs = getattr(self.ireq, "_source_ireqs", [])
            lines.extend(f"  {ireq}" for ireq in source_ireqs)
        else:
            redacted_urls = tuple(
                redact_auth_from_url(url) for url in self.finder.index_urls
            )
            lines.append("No versions found")
            lines.append(
                "{} {} reachable?".format(
                    "Were" if len(redacted_urls) > 1 else "Was",
                    " or ".join(redacted_urls),
                )
            )
        return "\n".join(lines)


class IncompatibleRequirements(PipToolsError):
    def __init__(self, ireq_a: InstallRequirement, ireq_b: InstallRequirement) -> None:
        self.ireq_a = ireq_a
        self.ireq_b = ireq_b

    def __str__(self) -> str:
        message = "Incompatible requirements found: {} and {}"
        return message.format(self.ireq_a, self.ireq_b)


================================================
FILE: piptools/locations.py
================================================
from __future__ import annotations

from pip._internal.utils.appdirs import user_cache_dir

# The user_cache_dir helper comes straight from pip itself
CACHE_DIR = user_cache_dir("pip-tools")

# The project defaults specific to pip-tools should be written to this filenames
DEFAULT_CONFIG_FILE_NAMES = (".pip-tools.toml", "pyproject.toml")


================================================
FILE: piptools/logging.py
================================================
from __future__ import annotations

import contextlib
import logging
import sys
import typing as _t
from collections.abc import Iterator

import click

# Initialise the builtin logging module for other component using it.
# Ex: pip
logging.basicConfig()


class LogContext:
    stream = sys.stderr

    def __init__(self, verbosity: int = 0, indent_width: int = 2):
        self.verbosity = self._initial_verbosity = verbosity
        self.current_indent = self._initial_indent = 0
        self._indent_width = self._initial_indent_width = indent_width

    def log(self, message: str, *args: _t.Any, **kwargs: _t.Any) -> None:
        kwargs.setdefault("err", True)
        prefix = " " * self.current_indent
        click.secho(prefix + message, *args, **kwargs)

    def debug(self, message: str, *args: _t.Any, **kwargs: _t.Any) -> None:
        if self.verbosity >= 1:
            self.log(message, *args, **kwargs)

    def info(self, message: str, *args: _t.Any, **kwargs: _t.Any) -> None:
        if self.verbosity >= 0:
            self.log(message, *args, **kwargs)

    def warning(self, message: str, *args: _t.Any, **kwargs: _t.Any) -> None:
        kwargs.setdefault("fg", "yellow")
        self.log(message, *args, **kwargs)

    def error(self, message: str, *args: _t.Any, **kwargs: _t.Any) -> None:
        kwargs.setdefault("fg", "red")
        self.log(message, *args, **kwargs)

    def _indent(self) -> None:
        self.current_indent += self._indent_width

    def _dedent(self) -> None:
        self.current_indent -= self._indent_width

    @contextlib.contextmanager
    def indentation(self) -> Iterator[None]:
        """
        Increase indentation.
        """
        self._indent()
        try:
            yield
        finally:
            self._dedent()

    def reset(self) -> None:
        """Reset logger to initial state."""
        self.verbosity = self._initial_verbosity
        self.current_indent = self._initial_indent
        self._indent_width = self._initial_indent_width


log = LogContext()


================================================
FILE: piptools/py.typed
================================================


================================================
FILE: piptools/repositories/__init__.py
================================================
from __future__ import annotations

from .local import LocalRequirementsRepository
from .pypi import PyPIRepository

__all__ = ["LocalRequirementsRepository", "PyPIRepository"]


================================================
FILE: piptools/repositories/base.py
================================================
from __future__ import annotations

import optparse
from abc import ABCMeta, abstractmethod
from collections.abc import Iterator
from contextlib import contextmanager

from pip._internal.commands.install import InstallCommand
from pip._internal.index.package_finder import PackageFinder
from pip._internal.models.index import PyPI
from pip._internal.network.session import PipSession
from pip._internal.req import InstallRequirement


class BaseRepository(metaclass=ABCMeta):
    DEFAULT_INDEX_URL = PyPI.simple_url

    def clear_caches(self) -> None:
        """Should clear any caches used by the implementation."""

    @abstractmethod
    def find_best_match(
        self, ireq: InstallRequirement, prereleases: bool | None
    ) -> InstallRequirement:
        """
        Returns a pinned InstallRequirement object that indicates the best match
        for the given InstallRequirement according to the external repository.
        """

    @abstractmethod
    def get_dependencies(self, ireq: InstallRequirement) -> set[InstallRequirement]:
        """
        Given a pinned, URL, or editable InstallRequirement, returns a set of
        dependencies (also InstallRequirements, but not necessarily pinned).
        They indicate the secondary dependencies for the given requirement.
        """

    @abstractmethod
    def get_hashes(self, ireq: InstallRequirement) -> set[str]:
        """
        Given a pinned InstallRequirement, returns a set of hashes that represent
        all of the files for a given requirement. It is not acceptable for an
        editable or unpinned requirement to be passed to this function.
        """

    @abstractmethod
    @contextmanager
    def allow_all_wheels(self) -> Iterator[None]:
        """
        Monkey patches pip.Wheel to allow wheels from all platforms and Python versions.
        """

    @property
    @abstractmethod
    def options(self) -> optparse.Values:
        """Returns parsed pip options"""

    @property
    @abstractmethod
    def session(self) -> PipSession:
        """Returns a session to make requests"""

    @property
    @abstractmethod
    def finder(self) -> PackageFinder:
        """Returns a package finder to interact with simple repository API (PEP 503)"""

    @property
    @abstractmethod
    def command(self) -> InstallCommand:
        """Return an install command."""


================================================
FILE: piptools/repositories/local.py
================================================
from __future__ import annotations

import optparse
import typing as _t
from collections.abc import Iterator, Mapping
from contextlib import contextmanager

from pip._internal.commands.install import InstallCommand
from pip._internal.index.package_finder import PackageFinder
from pip._internal.models.candidate import InstallationCandidate
from pip._internal.network.session import PipSession
from pip._internal.req import InstallRequirement
from pip._internal.utils.hashes import FAVORITE_HASH

from .._internal import _pip_api
from ..utils import as_tuple, key_from_ireq
from .base import BaseRepository
from .pypi import PyPIRepository


def ireq_satisfied_by_existing_pin(
    ireq: InstallRequirement, existing_pin: InstallationCandidate
) -> bool:
    """
    Return :py:data:`True` if the given ``InstallRequirement`` is satisfied by the
    previously encountered version pin.
    """
    version = next(iter(existing_pin.req.specifier)).version
    result = ireq.req.specifier.contains(
        version, prereleases=existing_pin.req.specifier.prereleases
    )
    return _t.cast(bool, result)


class LocalRequirementsRepository(BaseRepository):
    """
    The LocalRequirementsRepository proxied the _real_ repository by first
    checking if a requirement can be satisfied by existing pins (i.e. the
    result of a previous compile step).

    In effect, if a requirement can be satisfied with a version pinned in the
    requirements file, we prefer that version over the best match found in
    PyPI.  This keeps updates to the requirements.txt down to a minimum.
    """

    def __init__(
        self,
        existing_pins: Mapping[str, InstallationCandidate],
        proxied_repository: PyPIRepository,
        reuse_hashes: bool = True,
    ):
        self._reuse_hashes = reuse_hashes
        self.repository = proxied_repository
        self.existing_pins = existing_pins

    @property
    def options(self) -> optparse.Values:
        return self.repository.options

    @property
    def finder(self) -> PackageFinder:
        return self.repository.finder

    @property
    def session(self) -> PipSession:
        return self.repository.session

    @property
    def command(self) -> InstallCommand:
        """Return an install command instance."""
        return self.repository.command

    def clear_caches(self) -> None:
        self.repository.clear_caches()

    def find_best_match(
        self, ireq: InstallRequirement, prereleases: bool | None = None
    ) -> InstallationCandidate:
        key = key_from_ireq(ireq)
        existing_pin = self.existing_pins.get(key)
        if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):
            project, version, _ = as_tuple(existing_pin)
            return _pip_api.create_install_requirement(project, version, ireq)
        else:
            return self.repository.find_best_match(ireq, prereleases)

    def get_dependencies(self, ireq: InstallRequirement) -> set[InstallRequirement]:
        return self.repository.get_dependencies(ireq)

    def get_hashes(self, ireq: InstallRequirement) -> set[str]:
        existing_pin = self._reuse_hashes and self.existing_pins.get(
            key_from_ireq(ireq)
        )
        if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):
            hashes = existing_pin.hash_options
            hexdigests = hashes.get(FAVORITE_HASH)
            if hexdigests:
                return {
                    ":".join([FAVORITE_HASH, hexdigest]) for hexdigest in hexdigests
                }
        return self.repository.get_hashes(ireq)

    @contextmanager
    def allow_all_wheels(self) -> Iterator[None]:
        with self.repository.allow_all_wheels():
            yield


================================================
FILE: piptools/repositories/pypi.py
================================================
from __future__ import annotations

import contextlib
import hashlib
import itertools
import optparse
import os
import typing as _t
from collections.abc import Iterator
from contextlib import contextmanager
from shutil import rmtree

from click import progressbar
from pip._internal.cache import WheelCache
from pip._internal.commands import create_command
from pip._internal.commands.install import InstallCommand
from pip._internal.index.package_finder import PackageFinder
from pip._internal.models.candidate import InstallationCandidate
from pip._internal.models.index import PackageIndex
from pip._internal.models.link import Link
from pip._internal.models.wheel import Wheel
from pip._internal.network.session import PipSession
from pip._internal.operations.build.build_tracker import get_build_tracker
from pip._internal.req import InstallRequirement, RequirementSet
from pip._internal.utils.hashes import FAVORITE_HASH
from pip._internal.utils.logging import indent_log, setup_logging
from pip._internal.utils.misc import normalize_path
from pip._internal.utils.temp_dir import TempDirectory, global_tempdir_manager
from pip._internal.utils.urls import path_to_url, url_to_path
from pip._vendor.packaging.tags import Tag
from pip._vendor.packaging.version import _BaseVersion
from pip._vendor.requests import RequestException, Session

from .._compat import create_wheel_cache
from .._internal import _pip_api
from ..exceptions import NoCandidateFound
from ..logging import log
from ..utils import (
    as_tuple,
    is_pinned_requirement,
    is_url_requirement,
    lookup_table,
)
from .base import BaseRepository

FILE_CHUNK_SIZE = 4096


class FileStream(_t.NamedTuple):
    stream: _t.BinaryIO
    size: float | None


class PyPIRepository(BaseRepository):
    HASHABLE_PACKAGE_TYPES = {"bdist_wheel", "sdist"}

    """
    The PyPIRepository will use the provided Finder instance to lookup
    packages.  Typically, it looks up packages on PyPI (the default implicit
    config), but any other PyPI mirror can be used if index_urls is
    changed/configured on the Finder.
    """

    def __init__(self, pip_args: list[str], cache_dir: str):
        # Use pip's parser for pip.conf management and defaults.
        # General options (find_links, index_url, extra_index_url, trusted_host,
        # and pre) are deferred to pip.
        self._command: InstallCommand = create_command("install")

        options, _ = self.command.parse_args(pip_args)
        _pip_api.postprocess_cli_options(options)

        if options.cache_dir:
            options.cache_dir = normalize_path(options.cache_dir)
        options.require_hashes = False
        options.ignore_dependencies = False

        self._options: optparse.Values = options
        self._session = self.command._build_session(options)
        self._finder = self.command._build_package_finder(
            options=options, session=self.session
        )

        # Caches
        # stores project_name => InstallationCandidate mappings for all
        # versions reported by PyPI, so we only have to ask once for each
        # project
        self._available_candidates_cache: dict[str, list[InstallationCandidate]] =
Download .txt
gitextract_04gc2qn3/

├── .bandit
├── .codecov.yml
├── .coveragerc
├── .flake8
├── .git_archival.txt
├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.md
│   │   └── feature-request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── actions/
│   │   └── cache-keys/
│   │       └── action.yml
│   ├── chronographer.yml
│   ├── reusables/
│   │   └── tox-dev/
│   │       └── workflow/
│   │           └── reusable-tox/
│   │               └── hooks/
│   │                   └── post-tox-run/
│   │                       └── action.yml
│   └── workflows/
│       ├── ci.yml
│       ├── cron.yml
│       ├── release.yml
│       └── reusable-qa.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .pre-commit-hooks.yaml
├── .pymarkdown.yml
├── .readthedocs.yaml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── MANIFEST.in
├── README.md
├── changelog.d/
│   ├── .draft_changelog_partial.md
│   ├── .gitignore
│   ├── .towncrier_template.md.jinja
│   ├── 1142.feature.md
│   ├── 2318.contrib.md
│   ├── 2327.contrib.md
│   ├── 2343.contrib.md
│   └── README.md
├── docs/
│   ├── .gitignore
│   ├── changelog.md
│   ├── cli/
│   │   ├── index.md
│   │   ├── pip-compile.md
│   │   └── pip-sync.md
│   ├── conf.py
│   ├── contributing.md
│   ├── index.md
│   ├── pkg/
│   │   └── .gitignore
│   ├── requirements.in
│   └── requirements.txt
├── examples/
│   ├── django.in
│   ├── flask.in
│   ├── hypothesis.in
│   ├── protection.in
│   ├── readme/
│   │   ├── constraints.txt
│   │   └── pyproject.toml
│   └── sentry.in
├── piptools/
│   ├── __init__.py
│   ├── __main__.py
│   ├── _compat/
│   │   ├── __init__.py
│   │   ├── _tomllib_compat.py
│   │   ├── path_compat.py
│   │   ├── pip_compat.py
│   │   └── tempfile_compat.py
│   ├── _internal/
│   │   ├── __init__.py
│   │   ├── _pip_api/
│   │   │   ├── __init__.py
│   │   │   ├── cli_options.py
│   │   │   ├── install_requirements.py
│   │   │   ├── package_finder.py
│   │   │   └── pip_version.py
│   │   └── _subprocess.py
│   ├── build.py
│   ├── cache.py
│   ├── exceptions.py
│   ├── locations.py
│   ├── logging.py
│   ├── py.typed
│   ├── repositories/
│   │   ├── __init__.py
│   │   ├── base.py
│   │   ├── local.py
│   │   └── pypi.py
│   ├── resolver.py
│   ├── scripts/
│   │   ├── __init__.py
│   │   ├── _deprecations.py
│   │   ├── compile.py
│   │   ├── options.py
│   │   └── sync.py
│   ├── sync.py
│   ├── utils.py
│   └── writer.py
├── pyproject.toml
├── tests/
│   ├── __init__.py
│   ├── conftest.py
│   ├── constants.py
│   ├── test_build.py
│   ├── test_cache.py
│   ├── test_circular_imports.py
│   ├── test_cli_compile.py
│   ├── test_cli_sync.py
│   ├── test_data/
│   │   ├── fake-editables.json
│   │   ├── fake-index.json
│   │   ├── minimal_wheels/
│   │   │   ├── small_fake_a-0.1-py2.py3-none-any.whl
│   │   │   ├── small_fake_a-0.2-py2.py3-none-any.whl
│   │   │   ├── small_fake_a-0.3b1-py2.py3-none-any.whl
│   │   │   ├── small_fake_b-0.1-py2.py3-none-any.whl
│   │   │   ├── small_fake_b-0.2-py2.py3-none-any.whl
│   │   │   ├── small_fake_b-0.3-py2.py3-none-any.whl
│   │   │   ├── small_fake_multi_arch-0.1-py2.py3-none-manylinux1_i686.whl
│   │   │   ├── small_fake_multi_arch-0.1-py2.py3-none-manylinux1_x86_64.whl
│   │   │   ├── small_fake_multi_arch-0.1-py2.py3-none-win32.whl
│   │   │   ├── small_fake_with_deps-0.1-py2.py3-none-any.whl
│   │   │   ├── small_fake_with_deps_and_sub_deps-0.1-py2.py3-none-any.whl
│   │   │   └── small_fake_with_unpinned_deps-0.1-py2.py3-none-any.whl
│   │   └── packages/
│   │       ├── fake_with_deps/
│   │       │   ├── fake_with_deps/
│   │       │   │   └── __init__.py
│   │       │   └── pyproject.toml
│   │       ├── small_fake_a/
│   │       │   └── setup.py
│   │       ├── small_fake_with_build_deps/
│   │       │   ├── backend/
│   │       │   │   └── backend.py
│   │       │   ├── pyproject.toml
│   │       │   └── setup.py
│   │       ├── small_fake_with_deps/
│   │       │   └── setup.py
│   │       ├── small_fake_with_deps_and_sub_deps/
│   │       │   └── setup.py
│   │       ├── small_fake_with_pyproject/
│   │       │   └── pyproject.toml
│   │       ├── small_fake_with_subdir/
│   │       │   └── subdir/
│   │       │       └── setup.py
│   │       └── small_fake_with_unpinned_deps/
│   │           └── setup.py
│   ├── test_fake_index.py
│   ├── test_logging.py
│   ├── test_minimal_upgrade.py
│   ├── test_pip_compat.py
│   ├── test_repository_local.py
│   ├── test_repository_pypi.py
│   ├── test_resolver.py
│   ├── test_sync.py
│   ├── test_top_level_editable.py
│   ├── test_utils.py
│   ├── test_writer.py
│   ├── unit/
│   │   └── _internal/
│   │       ├── pip_api/
│   │       │   ├── test_cli_options.py
│   │       │   ├── test_install_requirements.py
│   │       │   ├── test_package_finder.py
│   │       │   └── test_pip_version.py
│   │       └── test_subprocess.py
│   └── utils.py
├── towncrier.toml
└── tox.ini
Download .txt
SYMBOL INDEX (612 symbols across 48 files)

FILE: docs/conf.py
  function setup (line 138) | def setup(app: Sphinx) -> dict[str, bool | str]:

FILE: piptools/__main__.py
  function cli (line 9) | def cli() -> None:

FILE: piptools/_compat/path_compat.py
  function relative_to_walk_up (line 15) | def relative_to_walk_up(path: pathlib.Path, start: pathlib.Path) -> path...

FILE: piptools/_compat/pip_compat.py
  function canonicalize_name (line 34) | def canonicalize_name(name: str) -> str: ...
  class Distribution (line 43) | class Distribution:
    method from_pip_distribution (line 50) | def from_pip_distribution(cls, dist: BaseDistribution) -> Distribution:
    method _from_pkg_resources (line 59) | def _from_pkg_resources(cls, dist: _PkgResourcesDist) -> Distribution:
    method _from_importlib (line 65) | def _from_importlib(cls, dist: _ImportLibDist) -> Distribution:
  class FileLink (line 81) | class FileLink(Link):  # type: ignore[misc]
    method file_path (line 87) | def file_path(self) -> str:
  function parse_requirements (line 92) | def parse_requirements(
  function _rewrite_comes_from_to_hardcoded_stdin_value (line 133) | def _rewrite_comes_from_to_hardcoded_stdin_value(_: str, /) -> str:
  function _relativize_comes_from_location (line 138) | def _relativize_comes_from_location(original_comes_from: str, /) -> str:
  function _normalize_comes_from_location (line 170) | def _normalize_comes_from_location(original_comes_from: str, /) -> str:
  function _is_remote_pip_uri (line 197) | def _is_remote_pip_uri(value: str) -> bool:
  function create_wheel_cache (line 208) | def create_wheel_cache(cache_dir: str, format_control: str | None = None...
  function get_dev_pkgs (line 215) | def get_dev_pkgs() -> set[str]:

FILE: piptools/_compat/tempfile_compat.py
  function named_temp_file (line 18) | def named_temp_file(mode: str = "wt") -> _c.Iterator[_t.IO[str]]:

FILE: piptools/_internal/_pip_api/cli_options.py
  function postprocess_cli_options (line 14) | def postprocess_cli_options(options: optparse.Values) -> None:

FILE: piptools/_internal/_pip_api/install_requirements.py
  function create_install_requirement (line 14) | def create_install_requirement(
  function create_install_requirement_from_line (line 37) | def create_install_requirement_from_line(
  function copy_install_requirement (line 43) | def copy_install_requirement(

FILE: piptools/_internal/_pip_api/package_finder.py
  function finder_allows_prereleases_of_req (line 16) | def finder_allows_prereleases_of_req(
  function finder_allows_all_prereleases (line 33) | def finder_allows_all_prereleases(finder: PackageFinder) -> bool:

FILE: piptools/_internal/_pip_api/pip_version.py
  function get_pip_version_for_python_executable (line 16) | def get_pip_version_for_python_executable(python_executable: str) -> Ver...

FILE: piptools/_internal/_subprocess.py
  function run_python_snippet (line 8) | def run_python_snippet(python_executable: str, code_to_run: str) -> str:

FILE: piptools/build.py
  class PackageMetadata (line 34) | class PackageMetadata(_t.Protocol):
    method get_all (line 36) | def get_all(self, name: str, failobj: None = None) -> list[_t.Any] | N...
    method get_all (line 39) | def get_all(self, name: str, failobj: _T) -> list[_t.Any] | _T: ...
  class StaticProjectMetadata (line 43) | class StaticProjectMetadata:
  class ProjectMetadata (line 49) | class ProjectMetadata:
  function maybe_statically_parse_project_metadata (line 55) | def maybe_statically_parse_project_metadata(
  function build_project_metadata (line 117) | def build_project_metadata(
  function _env_var (line 189) | def _env_var(
  function _temporary_constraints_file_set_for_pip (line 212) | def _temporary_constraints_file_set_for_pip(
  function _create_project_builder (line 255) | def _create_project_builder(
  function _build_project_wheel_metadata (line 284) | def _build_project_wheel_metadata(
  function _get_name (line 292) | def _get_name(metadata: PackageMetadata) -> str:
  function _prepare_requirements (line 298) | def _prepare_requirements(
  function _prepare_build_requirements (line 326) | def _prepare_build_requirements(

FILE: piptools/cache.py
  function _implementation_name (line 23) | def _implementation_name() -> str:
  class CorruptCacheError (line 35) | class CorruptCacheError(PipToolsError):
    method __init__ (line 36) | def __init__(self, path: str):
    method __str__ (line 39) | def __str__(self) -> str:
  function read_cache_file (line 48) | def read_cache_file(cache_file_path: str) -> CacheDict:
  class DependencyCache (line 61) | class DependencyCache:
    method __init__ (line 74) | def __init__(self, cache_dir: str):
    method cache (line 82) | def cache(self) -> CacheDict:
    method as_cache_key (line 94) | def as_cache_key(self, ireq: InstallRequirement) -> CacheKey:
    method write_cache (line 116) | def write_cache(self) -> None:
    method clear (line 122) | def clear(self) -> None:
    method __contains__ (line 126) | def __contains__(self, ireq: InstallRequirement) -> bool:
    method __getitem__ (line 130) | def __getitem__(self, ireq: InstallRequirement) -> list[str]:
    method __setitem__ (line 134) | def __setitem__(self, ireq: InstallRequirement, values: list[str]) -> ...
    method reverse_dependencies (line 140) | def reverse_dependencies(
    method _reverse_dependencies (line 154) | def _reverse_dependencies(

FILE: piptools/exceptions.py
  class PipToolsError (line 14) | class PipToolsError(Exception):
  class NoCandidateFound (line 18) | class NoCandidateFound(PipToolsError):
    method __init__ (line 19) | def __init__(
    method __str__ (line 29) | def __str__(self) -> str:
  class IncompatibleRequirements (line 76) | class IncompatibleRequirements(PipToolsError):
    method __init__ (line 77) | def __init__(self, ireq_a: InstallRequirement, ireq_b: InstallRequirem...
    method __str__ (line 81) | def __str__(self) -> str:

FILE: piptools/logging.py
  class LogContext (line 16) | class LogContext:
    method __init__ (line 19) | def __init__(self, verbosity: int = 0, indent_width: int = 2):
    method log (line 24) | def log(self, message: str, *args: _t.Any, **kwargs: _t.Any) -> None:
    method debug (line 29) | def debug(self, message: str, *args: _t.Any, **kwargs: _t.Any) -> None:
    method info (line 33) | def info(self, message: str, *args: _t.Any, **kwargs: _t.Any) -> None:
    method warning (line 37) | def warning(self, message: str, *args: _t.Any, **kwargs: _t.Any) -> None:
    method error (line 41) | def error(self, message: str, *args: _t.Any, **kwargs: _t.Any) -> None:
    method _indent (line 45) | def _indent(self) -> None:
    method _dedent (line 48) | def _dedent(self) -> None:
    method indentation (line 52) | def indentation(self) -> Iterator[None]:
    method reset (line 62) | def reset(self) -> None:

FILE: piptools/repositories/base.py
  class BaseRepository (line 15) | class BaseRepository(metaclass=ABCMeta):
    method clear_caches (line 18) | def clear_caches(self) -> None:
    method find_best_match (line 22) | def find_best_match(
    method get_dependencies (line 31) | def get_dependencies(self, ireq: InstallRequirement) -> set[InstallReq...
    method get_hashes (line 39) | def get_hashes(self, ireq: InstallRequirement) -> set[str]:
    method allow_all_wheels (line 48) | def allow_all_wheels(self) -> Iterator[None]:
    method options (line 55) | def options(self) -> optparse.Values:
    method session (line 60) | def session(self) -> PipSession:
    method finder (line 65) | def finder(self) -> PackageFinder:
    method command (line 70) | def command(self) -> InstallCommand:

FILE: piptools/repositories/local.py
  function ireq_satisfied_by_existing_pin (line 21) | def ireq_satisfied_by_existing_pin(
  class LocalRequirementsRepository (line 35) | class LocalRequirementsRepository(BaseRepository):
    method __init__ (line 46) | def __init__(
    method options (line 57) | def options(self) -> optparse.Values:
    method finder (line 61) | def finder(self) -> PackageFinder:
    method session (line 65) | def session(self) -> PipSession:
    method command (line 69) | def command(self) -> InstallCommand:
    method clear_caches (line 73) | def clear_caches(self) -> None:
    method find_best_match (line 76) | def find_best_match(
    method get_dependencies (line 87) | def get_dependencies(self, ireq: InstallRequirement) -> set[InstallReq...
    method get_hashes (line 90) | def get_hashes(self, ireq: InstallRequirement) -> set[str]:
    method allow_all_wheels (line 104) | def allow_all_wheels(self) -> Iterator[None]:

FILE: piptools/repositories/pypi.py
  class FileStream (line 49) | class FileStream(_t.NamedTuple):
  class PyPIRepository (line 54) | class PyPIRepository(BaseRepository):
    method __init__ (line 64) | def __init__(self, pip_args: list[str], cache_dir: str):
    method clear_caches (line 106) | def clear_caches(self) -> None:
    method options (line 110) | def options(self) -> optparse.Values:
    method session (line 114) | def session(self) -> PipSession:
    method finder (line 118) | def finder(self) -> PackageFinder:
    method _clear_finder_cache (line 121) | def _clear_finder_cache(self) -> None:
    method command (line 136) | def command(self) -> InstallCommand:
    method find_all_candidates (line 140) | def find_all_candidates(self, req_name: str) -> list[InstallationCandi...
    method find_best_match (line 146) | def find_best_match(
    method resolve_reqs (line 181) | def resolve_reqs(
    method get_dependencies (line 229) | def get_dependencies(self, ireq: InstallRequirement) -> set[InstallReq...
    method _get_project (line 267) | def _get_project(self, ireq: InstallRequirement) -> _t.Any:
    method _get_download_path (line 300) | def _get_download_path(self, ireq: InstallRequirement) -> str:
    method get_hashes (line 315) | def get_hashes(self, ireq: InstallRequirement) -> set[str]:
    method _get_req_hashes (line 350) | def _get_req_hashes(self, ireq: InstallRequirement) -> set[str]:
    method _get_hashes_from_pypi (line 369) | def _get_hashes_from_pypi(self, ireq: InstallRequirement) -> dict[str,...
    method _get_matching_candidates (line 398) | def _get_matching_candidates(
    method _get_file_hash (line 414) | def _get_file_hash(self, link: Link) -> str:
    method allow_all_wheels (line 445) | def allow_all_wheels(self) -> Iterator[None]:
  function open_local_or_remote_file (line 483) | def open_local_or_remote_file(link: Link, session: Session) -> Iterator[...
  function candidate_version (line 521) | def candidate_version(candidate: InstallationCandidate) -> _BaseVersion:

FILE: piptools/resolver.py
  class RequirementSummary (line 50) | class RequirementSummary:
    method __init__ (line 55) | def __init__(self, ireq: InstallRequirement) -> None:
    method __eq__ (line 61) | def __eq__(self, other: object) -> bool:
    method __hash__ (line 71) | def __hash__(self) -> int:
    method __str__ (line 74) | def __str__(self) -> str:
  function combine_install_requirements (line 78) | def combine_install_requirements(
  class BaseResolver (line 148) | class BaseResolver(metaclass=ABCMeta):
    method resolve (line 153) | def resolve(self, max_rounds: int) -> set[InstallRequirement]:
    method resolve_hashes (line 160) | def resolve_hashes(
    method _filter_out_unsafe_constraints (line 171) | def _filter_out_unsafe_constraints(
  class LegacyResolver (line 185) | class LegacyResolver(BaseResolver):
    method __init__ (line 190) | def __init__(
    method constraints (line 240) | def constraints(self) -> set[InstallRequirement]:
    method resolve (line 245) | def resolve(self, max_rounds: int = 10) -> set[InstallRequirement]:
    method _group_constraints (line 297) | def _group_constraints(
    method _resolve_one_round (line 334) | def _resolve_one_round(self) -> tuple[bool, set[InstallRequirement]]:
    method get_best_match (line 396) | def get_best_match(self, ireq: InstallRequirement) -> InstallRequirement:
    method _iter_dependencies (line 440) | def _iter_dependencies(
    method _ireqs_of_dependencies (line 490) | def _ireqs_of_dependencies(
  class BacktrackingResolver (line 508) | class BacktrackingResolver(BaseResolver):
    method __init__ (line 511) | def __init__(
    method resolve (line 550) | def resolve(self, max_rounds: int = 10) -> set[InstallRequirement]:
    method _do_resolve (line 664) | def _do_resolve(
    method _get_install_requirements (line 716) | def _get_install_requirements(
    method _get_reverse_dependencies (line 753) | def _get_reverse_dependencies(
    method _get_install_requirement_from_candidate (line 778) | def _get_install_requirement_from_candidate(

FILE: piptools/scripts/_deprecations.py
  function filter_deprecated_pip_args (line 9) | def filter_deprecated_pip_args(args: list[str]) -> list[str]:

FILE: piptools/scripts/compile.py
  function _determine_linesep (line 47) | def _determine_linesep(
  function cli (line 144) | def cli(

FILE: piptools/scripts/options.py
  function help_option (line 22) | def help_option(*, epilog: str | None = None) -> _t.Callable[[_FC], _FC]:
  function _get_default_option (line 50) | def _get_default_option(option_name: str) -> _t.Any:

FILE: piptools/scripts/sync.py
  function cli (line 71) | def cli(
  function _validate_python_executable (line 174) | def _validate_python_executable(python_executable: str) -> None:
  function _compose_install_flags (line 198) | def _compose_install_flags(
  function _get_installed_distributions (line 260) | def _get_installed_distributions(

FILE: piptools/sync.py
  function dependency_tree (line 42) | def dependency_tree(
  function get_dists_to_ignore (line 81) | def get_dists_to_ignore(installed: Iterable[Distribution]) -> list[str]:
  function merge (line 96) | def merge(
  function diff_key_from_ireq (line 125) | def diff_key_from_ireq(ireq: InstallRequirement) -> str:
  function diff_key_from_req (line 146) | def diff_key_from_req(req: Distribution) -> str:
  function diff (line 159) | def diff(
  function sync (line 192) | def sync(

FILE: piptools/utils.py
  function key_from_ireq (line 54) | def key_from_ireq(ireq: InstallRequirement) -> str:
  function key_from_req (line 62) | def key_from_req(req: InstallRequirement | Requirement | PipRequirement)...
  function comment (line 79) | def comment(text: str) -> str:
  function is_url_requirement (line 83) | def is_url_requirement(ireq: InstallRequirement) -> bool:
  function format_requirement (line 92) | def format_requirement(
  function _build_direct_reference_best_efforts (line 122) | def _build_direct_reference_best_efforts(ireq: InstallRequirement) -> str:
  function format_specifier (line 157) | def format_specifier(ireq: InstallRequirement) -> str:
  function is_pinned_requirement (line 170) | def is_pinned_requirement(ireq: InstallRequirement) -> bool:
  function as_tuple (line 197) | def as_tuple(ireq: InstallRequirement) -> tuple[str, str, tuple[str, ...]]:
  function flat_map (line 211) | def flat_map(
  function lookup_table_from_tuples (line 218) | def lookup_table_from_tuples(values: Iterable[tuple[_KT, _VT]]) -> dict[...
  function lookup_table (line 226) | def lookup_table(
  function dedup (line 233) | def dedup(iterable: Iterable[_T]) -> Iterable[_T]:
  function drop_extras (line 241) | def drop_extras(ireq: InstallRequirement) -> None:
  function _drop_extras (line 250) | def _drop_extras(markers: list[_T]) -> list[_T]:
  function get_hashes_from_ireq (line 292) | def get_hashes_from_ireq(ireq: InstallRequirement) -> set[str]:
  function get_compile_command (line 305) | def get_compile_command(click_ctx: click.Context) -> str:
  function get_required_pip_specification (line 404) | def get_required_pip_specification() -> SpecifierSet:
  function get_sys_path_for_python_executable (line 418) | def get_sys_path_for_python_executable(python_executable: str) -> list[s...
  function omit_list_value (line 432) | def omit_list_value(lst: list[_T], value: _T) -> list[_T]:
  function strip_extras (line 440) | def strip_extras(name: str) -> str:
  function override_defaults_from_config_file (line 445) | def override_defaults_from_config_file(
  function _assign_config_to_cli_context (line 478) | def _assign_config_to_cli_context(
  function _validate_config (line 488) | def _validate_config(
  function select_config_file (line 544) | def select_config_file(src_files: tuple[str, ...]) -> Path | None:
  function get_cli_options (line 576) | def get_cli_options(ctx: click.Context) -> dict[str, click.Parameter]:
  function parse_config_file (line 586) | def parse_config_file(
  function _normalize_keys_in_config (line 622) | def _normalize_keys_in_config(config: dict[str, _t.Any]) -> dict[str, _t...
  function _invert_negative_bool_options_in_config (line 626) | def _invert_negative_bool_options_in_config(
  function _normalize_config_key (line 657) | def _normalize_config_key(key: str) -> str:
  function _convert_to_long_option (line 662) | def _convert_to_long_option(key: str) -> str:

FILE: piptools/writer.py
  function _comes_from_as_string (line 62) | def _comes_from_as_string(comes_from: str | InstallRequirement) -> str:
  function annotation_style_split (line 68) | def annotation_style_split(required_by: set[str]) -> str:
  function annotation_style_line (line 81) | def annotation_style_line(required_by: set[str]) -> str:
  class OutputWriter (line 85) | class OutputWriter:
    method __init__ (line 86) | def __init__(
    method _sort_key (line 128) | def _sort_key(self, ireq: InstallRequirement) -> tuple[bool, str]:
    method write_header (line 131) | def write_header(self) -> Iterator[str]:
    method write_index_options (line 146) | def write_index_options(self) -> Iterator[str]:
    method write_trusted_hosts (line 154) | def write_trusted_hosts(self) -> Iterator[str]:
    method write_format_controls (line 159) | def write_format_controls(self) -> Iterator[str]:
    method write_find_links (line 183) | def write_find_links(self) -> Iterator[str]:
    method write_flags (line 188) | def write_flags(self) -> Iterator[str]:
    method _iter_lines (line 203) | def _iter_lines(
    method write (line 271) | def write(
    method _format_requirement (line 291) | def _format_requirement(
  class _LineWriter (line 342) | class _LineWriter(_t.Protocol):
    method __call__ (line 343) | def __call__(self, line: str) -> None: ...
  function _dry_run_line_writer (line 346) | def _dry_run_line_writer(line: str) -> None:
  class _FileLineWriter (line 350) | class _FileLineWriter:
    method __init__ (line 351) | def __init__(self, dst_file: _t.BinaryIO, linesep: str) -> None:
    method __call__ (line 359) | def __call__(self, line: str) -> None:
    method __enter__ (line 364) | def __enter__(self) -> _t_Self:
    method __exit__ (line 367) | def __exit__(

FILE: tests/conftest.py
  class FakeOptions (line 53) | class FakeOptions:
  class FakeRepository (line 59) | class FakeRepository(BaseRepository):
    method __init__ (line 60) | def __init__(self, options: FakeOptions):
    method get_hashes (line 69) | def get_hashes(self, ireq):
    method find_best_match (line 76) | def find_best_match(self, ireq, prereleases=False):
    method get_dependencies (line 96) | def get_dependencies(self, ireq):
    method allow_all_wheels (line 112) | def allow_all_wheels(self):
    method options (line 117) | def options(self):
    method session (line 121) | def session(self) -> PipSession:
    method finder (line 125) | def finder(self) -> PackageFinder:
    method command (line 129) | def command(self) -> InstallCommand:
  function pytest_collection_modifyitems (line 133) | def pytest_collection_modifyitems(config, items):
  function fake_dist (line 141) | def fake_dist():
  function repository (line 161) | def repository():
  function pypi_repository (line 168) | def pypi_repository(tmpdir):
  function depcache (line 181) | def depcache(tmpdir):
  function resolver (line 186) | def resolver(depcache, repository):
  function backtracking_resolver (line 196) | def backtracking_resolver(depcache):
  function base_resolver (line 209) | def base_resolver(depcache):
  function from_line (line 214) | def from_line():
  function from_editable (line 227) | def from_editable():
  function runner (line 232) | def runner():
  function tmpdir_cwd (line 242) | def tmpdir_cwd(tmpdir):
  function make_pip_conf (line 248) | def make_pip_conf(tmpdir, monkeypatch):
  function pip_conf (line 271) | def pip_conf(make_pip_conf, minimal_wheels_path):
  function pip_with_index_conf (line 280) | def pip_with_index_conf(make_pip_conf, minimal_wheels_path):
  function make_package (line 289) | def make_package(tmp_path_factory):
  function run_setup_file (line 348) | def run_setup_file():
  function make_wheel (line 366) | def make_wheel(run_setup_file):
  function make_sdist (line 380) | def make_sdist(run_setup_file):
  function make_module (line 392) | def make_module(tmpdir):
  function fake_dists (line 424) | def fake_dists(tmp_path_factory, make_package, make_wheel):
  function fake_dists_with_build_deps (line 440) | def fake_dists_with_build_deps(tmp_path_factory, make_package, make_wheel):
  function venv (line 465) | def venv(tmp_path):
  function _reset_log (line 475) | def _reset_log():
  function make_config_file (line 485) | def make_config_file(tmpdir_cwd):
  function setuptools_wheel_path (line 516) | def setuptools_wheel_path(tmp_path_factory):
  function minimal_wheels_path (line 536) | def minimal_wheels_path(setuptools_wheel_path):

FILE: tests/test_build.py
  function test_build_project_metadata_resolved_correct_build_dependencies (line 20) | def test_build_project_metadata_resolved_correct_build_dependencies(
  function test_build_project_metadata_static (line 48) | def test_build_project_metadata_static(tmp_path):
  function test_build_project_metadata_raises_error (line 66) | def test_build_project_metadata_raises_error(tmp_path):
  function test_build_project_metadata_upgrading_raises_error (line 82) | def test_build_project_metadata_upgrading_raises_error(tmp_path):
  function test_static_parse_valid (line 110) | def test_static_parse_valid(tmp_path):
  function test_static_parse_of_self_referential_extra (line 133) | def test_static_parse_of_self_referential_extra(
  function test_static_parse_invalid (line 168) | def test_static_parse_invalid(tmp_path):
  function test_build_metadata_from_dynamic_dependencies (line 212) | def test_build_metadata_from_dynamic_dependencies(tmp_path):

FILE: tests/test_cache.py
  function _read_cache_file_helper (line 15) | def _read_cache_file_helper(to_write):
  function test_read_cache_file_not_json (line 37) | def test_read_cache_file_not_json():
  function test_read_cache_file_wrong_format (line 49) | def test_read_cache_file_wrong_format():
  function test_read_cache_file_successful (line 58) | def test_read_cache_file_successful():
  function test_read_cache_does_not_exist (line 68) | def test_read_cache_does_not_exist(tmpdir):
  function test_read_cache_permission_error (line 76) | def test_read_cache_permission_error(tmpdir):
  function test_reverse_dependencies (line 84) | def test_reverse_dependencies(from_line, tmpdir):

FILE: tests/test_circular_imports.py
  function _find_all_importables (line 30) | def _find_all_importables(pkg: ModuleType) -> list[str]:
  function _discover_path_importables (line 44) | def _discover_path_importables(pkg_pth: Path, pkg_name: str) -> Iterator...
  function _allowed_deprecation_warning_filters (line 66) | def _allowed_deprecation_warning_filters() -> list[str]:
  function test_no_warnings (line 99) | def test_no_warnings(import_path: str) -> None:

FILE: tests/test_cli_compile.py
  function pip_produces_absolute_paths (line 52) | def pip_produces_absolute_paths():
  class FileCollectionParam (line 59) | class FileCollectionParam:
    method __str__ (line 75) | def __str__(self) -> str:
    method populate (line 78) | def populate(self, tmp_path: pathlib.Path) -> None:
    method get_path_to (line 88) | def get_path_to(self, filename: str) -> str:
  class PackageVersionParam (line 98) | class PackageVersionParam:
    method __str__ (line 112) | def __str__(self) -> str:
    method as_req (line 115) | def as_req(self) -> str:
  function current_resolver (line 126) | def current_resolver(request, monkeypatch):
  function _temp_dep_cache (line 139) | def _temp_dep_cache(tmpdir, monkeypatch):
  function test_default_pip_conf_read (line 143) | def test_default_pip_conf_read(pip_with_index_conf, runner):
  function test_command_line_overrides_pip_conf (line 154) | def test_command_line_overrides_pip_conf(pip_with_index_conf, runner):
  function test_command_line_setuptools_read (line 190) | def test_command_line_setuptools_read(
  function test_command_line_setuptools_output_file (line 233) | def test_command_line_setuptools_output_file(runner, options, expected_o...
  function test_command_line_setuptools_nested_output_file (line 250) | def test_command_line_setuptools_nested_output_file(tmpdir, runner):
  function test_setuptools_preserves_environment_markers (line 268) | def test_setuptools_preserves_environment_markers(
  function test_no_index_option (line 303) | def test_no_index_option(runner, tmp_path):
  function test_find_links_option (line 313) | def test_find_links_option(runner):
  function test_find_links_envvar (line 330) | def test_find_links_envvar(monkeypatch, runner):
  function test_extra_index_option (line 348) | def test_extra_index_option(pip_with_index_conf, runner):
  function test_extra_index_envvar (line 374) | def test_extra_index_envvar(monkeypatch, runner):
  function test_redacted_urls_in_verbose_output (line 397) | def test_redacted_urls_in_verbose_output(runner, option):
  function test_trusted_host_option (line 420) | def test_trusted_host_option(pip_conf, runner):
  function test_trusted_host_envvar (line 429) | def test_trusted_host_envvar(monkeypatch, pip_conf, runner):
  function test_all_no_emit_options (line 452) | def test_all_no_emit_options(runner, options):
  function test_emit_index_url_option (line 470) | def test_emit_index_url_option(runner, option, expected_output):
  function test_realistic_complex_sub_dependencies (line 491) | def test_realistic_complex_sub_dependencies(runner, tmp_path):
  function test_run_as_module_compile (line 516) | def test_run_as_module_compile():
  function test_compile_help_opt_supports_short_and_long_flag (line 530) | def test_compile_help_opt_supports_short_and_long_flag(runner):
  function test_compile_help_opt_shows_examples_section (line 541) | def test_compile_help_opt_shows_examples_section(runner):
  function test_editable_package (line 551) | def test_editable_package(pip_conf, runner):
  function test_editable_package_without_non_editable_duplicate (line 565) | def test_editable_package_without_non_editable_duplicate(pip_conf, runner):
  function test_editable_package_constraint_without_non_editable_duplicate (line 590) | def test_editable_package_constraint_without_non_editable_duplicate(pip_...
  function test_editable_package_in_constraints (line 617) | def test_editable_package_in_constraints(pip_conf, runner, req_editable):
  function test_editable_package_vcs (line 640) | def test_editable_package_vcs(runner):
  function test_compile_cached_vcs_package (line 655) | def test_compile_cached_vcs_package(runner, venv):
  function test_locally_available_editable_package_is_not_archived_in_cache_dir (line 710) | def test_locally_available_editable_package_is_not_archived_in_cache_dir(
  function test_url_package (line 770) | def test_url_package(runner, line, dependency, generate_hashes):
  function test_local_file_uri_package (line 845) | def test_local_file_uri_package(
  function test_relative_file_uri_package (line 860) | def test_relative_file_uri_package(pip_conf, runner):
  function test_direct_reference_with_extras (line 875) | def test_direct_reference_with_extras(runner):
  function test_input_file_without_extension (line 890) | def test_input_file_without_extension(pip_conf, runner):
  function test_ignore_incompatible_existing_pins (line 905) | def test_ignore_incompatible_existing_pins(pip_conf, runner):
  function test_upgrade_packages_option (line 919) | def test_upgrade_packages_option(pip_conf, runner):
  function test_upgrade_packages_option_irrelevant (line 935) | def test_upgrade_packages_option_irrelevant(pip_conf, runner):
  function test_upgrade_packages_option_no_existing_file (line 951) | def test_upgrade_packages_option_no_existing_file(pip_conf, runner):
  function test_upgrade_packages_empty_target_file_warning (line 970) | def test_upgrade_packages_empty_target_file_warning(pip_conf, runner):
  function test_upgrade_packages_version_option (line 994) | def test_upgrade_packages_version_option(
  function test_upgrade_packages_version_option_no_existing_file (line 1013) | def test_upgrade_packages_version_option_no_existing_file(pip_conf, runn...
  function test_upgrade_packages_version_option_and_upgrade (line 1034) | def test_upgrade_packages_version_option_and_upgrade(pip_conf, runner, r...
  function test_upgrade_packages_version_option_and_upgrade_no_existing_file (line 1051) | def test_upgrade_packages_version_option_and_upgrade_no_existing_file(pi...
  function test_upgrade_package_with_extra (line 1066) | def test_upgrade_package_with_extra(runner, make_package, make_sdist, tm...
  function test_quiet_option (line 1111) | def test_quiet_option(pip_conf, runner):
  function test_dry_run_noisy_option (line 1120) | def test_dry_run_noisy_option(runner):
  function test_dry_run_quiet_option (line 1128) | def test_dry_run_quiet_option(runner):
  function test_generate_hashes_with_editable (line 1140) | def test_generate_hashes_with_editable(pip_conf, runner):
  function test_generate_hashes_with_url (line 1160) | def test_generate_hashes_with_url(runner):
  function test_generate_hashes_verbose (line 1177) | def test_generate_hashes_verbose(pip_conf, runner):
  function test_generate_hashes_with_annotations (line 1190) | def test_generate_hashes_with_annotations(runner):
  function test_override_newline (line 1235) | def test_override_newline(
  function test_preserve_newline_from_input (line 1289) | def test_preserve_newline_from_input(runner, linesep, must_exclude):
  function test_generate_hashes_with_split_style_annotations (line 1304) | def test_generate_hashes_with_split_style_annotations(pip_conf, runner, ...
  function test_generate_hashes_with_line_style_annotations (line 1337) | def test_generate_hashes_with_line_style_annotations(pip_conf, runner, t...
  function test_generate_hashes_with_mixed_sources (line 1369) | def test_generate_hashes_with_mixed_sources(
  function test_filter_pip_markers (line 1424) | def test_filter_pip_markers(pip_conf, runner):
  function test_bad_setup_file (line 1438) | def test_bad_setup_file(runner):
  function test_no_candidates (line 1449) | def test_no_candidates(pip_conf, runner):
  function test_no_candidates_pre (line 1460) | def test_no_candidates_pre(pip_conf, runner):
  function test_default_index_url (line 1481) | def test_default_index_url(make_pip_conf, url, expected_url):
  function test_stdin_without_output_file (line 1499) | def test_stdin_without_output_file(runner):
  function test_stdin (line 1509) | def test_stdin(pip_conf, runner):
  function test_tmpfile_for_stdin_is_cleaned_up (line 1525) | def test_tmpfile_for_stdin_is_cleaned_up(pip_conf, runner):
  function test_multiple_input_files_without_output_file (line 1573) | def test_multiple_input_files_without_output_file(runner):
  function test_annotate_option (line 1624) | def test_annotate_option(pip_conf, runner, options, expected):
  function test_allow_unsafe_option (line 1681) | def test_allow_unsafe_option(pip_conf, monkeypatch, runner, option, expe...
  function test_unsafe_package_option (line 1732) | def test_unsafe_package_option(pip_conf, monkeypatch, runner, unsafe_pac...
  function test_unsafe_package_option_normalizes (line 1764) | def test_unsafe_package_option_normalizes(pip_conf, runner, unsafe_packa...
  function test_cert_option (line 1806) | def test_cert_option(parse_requirements, runner, option, attr, expected):
  function test_parse_requirements_build_isolation_option (line 1825) | def test_parse_requirements_build_isolation_option(
  function test_build_project_metadata_isolation_option (line 1847) | def test_build_project_metadata_isolation_option(
  function test_forwarded_args (line 1869) | def test_forwarded_args(PyPIRepository, runner):
  function test_forwarded_args_filter_deprecated (line 1897) | def test_forwarded_args_filter_deprecated(PyPIRepository, runner, pip_ar...
  function test_pre_option (line 1926) | def test_pre_option(pip_conf, runner, cli_option, infile_option, expecte...
  function test_dry_run_option (line 1954) | def test_dry_run_option(pip_conf, runner, add_options):
  function test_dry_run_doesnt_touch_output_file (line 1982) | def test_dry_run_doesnt_touch_output_file(
  function test_empty_input_file_no_header (line 2019) | def test_empty_input_file_no_header(runner, empty_input_pkg, prior_outpu...
  function test_upgrade_package_doesnt_remove_annotation (line 2036) | def test_upgrade_package_doesnt_remove_annotation(pip_conf, runner):
  function test_many_inputs_includes_all_annotations (line 2064) | def test_many_inputs_includes_all_annotations(pip_conf, runner, tmp_path...
  function test_options_in_requirements_file (line 2110) | def test_options_in_requirements_file(runner, options):
  function test_unreachable_index_urls (line 2145) | def test_unreachable_index_urls(runner, cli_options, expected_message):
  function test_upgrade_packages_option_subdependency (line 2169) | def test_upgrade_packages_option_subdependency(
  function test_remove_outdated_options (line 2236) | def test_remove_outdated_options(runner, input_opts, output_opts):
  function test_sub_dependencies_with_constraints (line 2252) | def test_sub_dependencies_with_constraints(pip_conf, runner):
  function test_preserve_compiled_prerelease_version (line 2276) | def test_preserve_compiled_prerelease_version(pip_conf, runner):
  function test_ignore_compiled_unavailable_version (line 2290) | def test_ignore_compiled_unavailable_version(pip_conf, runner, current_r...
  function test_prefer_binary_dist (line 2310) | def test_prefer_binary_dist(
  function test_prefer_binary_dist_even_there_is_source_dists (line 2348) | def test_prefer_binary_dist_even_there_is_source_dists(
  function test_duplicate_reqs_combined (line 2383) | def test_duplicate_reqs_combined(
  function test_local_duplicate_subdependency_combined (line 2417) | def test_local_duplicate_subdependency_combined(runner, make_package):
  function test_combine_extras (line 2445) | def test_combine_extras(pip_conf, runner, make_package):
  function test_combine_different_extras_of_the_same_package (line 2477) | def test_combine_different_extras_of_the_same_package(
  function test_canonicalize_extras (line 2548) | def test_canonicalize_extras(pip_conf, runner, tmp_path, make_package, m...
  function test_triple_equal_pinned_dependency_is_used (line 2626) | def test_triple_equal_pinned_dependency_is_used(
  function test_not_specified_input_file (line 2749) | def test_not_specified_input_file(
  function test_not_specified_input_file_without_allowed_files (line 2776) | def test_not_specified_input_file_without_allowed_files(runner):
  function test_input_formats (line 2792) | def test_input_formats(fake_dists, runner, make_module, fname, content):
  function test_error_in_pyproject_toml (line 2808) | def test_error_in_pyproject_toml(
  function test_one_extra (line 2841) | def test_one_extra(fake_dists, runner, make_module, fname, content):
  function test_multiple_extras (line 2873) | def test_multiple_extras(fake_dists, runner, make_module, fname, content...
  function test_all_extras (line 2897) | def test_all_extras(fake_dists, runner, make_module, fname, content):
  function test_all_extras_fail_with_extra (line 2928) | def test_all_extras_fail_with_extra(fake_dists, runner, make_module, fna...
  function _mock_resolver_cls (line 2954) | def _mock_resolver_cls(monkeypatch: pytest.MonkeyPatch) -> MagicMock:
  function _mock_build_project_metadata (line 2966) | def _mock_build_project_metadata(monkeypatch: pytest.MonkeyPatch) -> Mag...
  function test_all_extras_and_all_build_deps (line 2985) | def test_all_extras_and_all_build_deps(
  function test_all_build_deps (line 3052) | def test_all_build_deps(runner, tmp_path, monkeypatch):
  function test_only_build_deps (line 3079) | def test_only_build_deps(runner, tmp_path, monkeypatch):
  function test_all_build_deps_fail_with_build_target (line 3102) | def test_all_build_deps_fail_with_build_target(runner):
  function test_only_build_deps_fails_without_any_build_deps (line 3120) | def test_only_build_deps_fails_without_any_build_deps(runner):
  function test_only_build_deps_fails_with_conflicting_options (line 3136) | def test_only_build_deps_fails_with_conflicting_options(runner, option):
  function test_build_deps_fail_without_setup_file (line 3155) | def test_build_deps_fail_without_setup_file(runner, tmpdir, option):
  function test_extras_fail_with_requirements_in (line 3171) | def test_extras_fail_with_requirements_in(runner, tmpdir):
  function test_cli_compile_strip_extras (line 3183) | def test_cli_compile_strip_extras(runner, make_package, make_sdist, tmpd...
  function test_cli_compile_all_extras_with_multiple_packages (line 3209) | def test_cli_compile_all_extras_with_multiple_packages(
  function test_resolver_drops_existing_conflicting_constraint (line 3336) | def test_resolver_drops_existing_conflicting_constraint(
  function test_resolution_failure (line 3376) | def test_resolution_failure(runner):
  function test_resolver_reaches_max_rounds (line 3386) | def test_resolver_reaches_max_rounds(runner):
  function test_preserve_via_requirements_constrained_dependencies_when_run_twice (line 3396) | def test_preserve_via_requirements_constrained_dependencies_when_run_twice(
  function test_failure_of_legacy_resolver_prompts_for_backtracking (line 3437) | def test_failure_of_legacy_resolver_prompts_for_backtracking(
  function test_print_deprecation_warning_if_using_legacy_resolver (line 3470) | def test_print_deprecation_warning_if_using_legacy_resolver(runner, curr...
  function test_raise_error_when_input_and_output_filenames_are_matched (line 3491) | def test_raise_error_when_input_and_output_filenames_are_matched(
  function test_pass_pip_cache_to_pip_args (line 3514) | def test_pass_pip_cache_to_pip_args(tmpdir, runner, current_resolver):
  function test_compile_recursive_extras_static (line 3533) | def test_compile_recursive_extras_static(
  function test_compile_recursive_extras_build_targets (line 3586) | def test_compile_recursive_extras_build_targets(
  function test_compile_build_targets_setuptools_no_wheel_dep (line 3643) | def test_compile_build_targets_setuptools_no_wheel_dep(
  function test_config_option (line 3709) | def test_config_option(pip_conf, runner, tmp_path, make_config_file):
  function test_default_config_option (line 3721) | def test_default_config_option(pip_conf, runner, make_config_file, tmpdi...
  function test_no_config_option_overrides_config_with_defaults (line 3733) | def test_no_config_option_overrides_config_with_defaults(
  function test_raise_error_on_unknown_config_option (line 3749) | def test_raise_error_on_unknown_config_option(
  function test_raise_error_on_invalid_config_option (line 3763) | def test_raise_error_on_invalid_config_option(
  function test_constraint_option (line 3778) | def test_constraint_option(pip_conf, runner, tmpdir_cwd, make_config_fil...
  function test_allow_in_config_pip_sync_option (line 3807) | def test_allow_in_config_pip_sync_option(pip_conf, runner, tmp_path, mak...
  function test_use_src_files_from_config_if_option_is_not_specified_from_cli (line 3821) | def test_use_src_files_from_config_if_option_is_not_specified_from_cli(
  function test_use_src_files_from_cli_if_option_is_specified_in_both_config_and_cli (line 3839) | def test_use_src_files_from_cli_if_option_is_specified_in_both_config_an...
  function test_cli_boolean_flag_config_option_has_valid_context (line 3857) | def test_cli_boolean_flag_config_option_has_valid_context(
  function test_invalid_cli_boolean_flag_config_option_captured (line 3880) | def test_invalid_cli_boolean_flag_config_option_captured(
  function test_show_warning_on_default_strip_extras_option (line 3899) | def test_show_warning_on_default_strip_extras_option(
  function test_do_not_show_warning_on_explicit_strip_extras_option (line 3912) | def test_do_not_show_warning_on_explicit_strip_extras_option(
  function test_origin_of_extra_requirement_not_written_to_annotations (line 3924) | def test_origin_of_extra_requirement_not_written_to_annotations(
  function test_tool_specific_config_option (line 3969) | def test_tool_specific_config_option(pip_conf, runner, tmp_path, make_co...
  function test_stdout_should_not_be_read_when_stdin_is_not_a_plain_file (line 3985) | def test_stdout_should_not_be_read_when_stdin_is_not_a_plain_file(
  function test_second_order_requirements_path_handling (line 4029) | def test_second_order_requirements_path_handling(
  function test_second_order_requirements_relative_path_in_separate_dir (line 4103) | def test_second_order_requirements_relative_path_in_separate_dir(
  function test_second_order_requirements_can_be_in_parent_of_cwd (line 4155) | def test_second_order_requirements_can_be_in_parent_of_cwd(
  function test_url_constraints_are_not_treated_as_file_paths (line 4200) | def test_url_constraints_are_not_treated_as_file_paths(
  function test_that_self_referential_pyproject_toml_extra_can_be_compiled (line 4274) | def test_that_self_referential_pyproject_toml_extra_can_be_compiled(
  function test_compile_with_generate_hashes_preserves_extra_index_url (line 4327) | def test_compile_with_generate_hashes_preserves_extra_index_url(

FILE: tests/test_cli_sync.py
  function _temp_default_reqs (line 16) | def _temp_default_reqs(tmp_path, monkeypatch):
  function test_run_as_module_sync (line 22) | def test_run_as_module_sync():
  function test_sync_help_opt_supports_short_and_long_flag (line 36) | def test_sync_help_opt_supports_short_and_long_flag(runner):
  function test_sync_help_opt_shows_examples_section (line 47) | def test_sync_help_opt_shows_examples_section(runner):
  function test_quiet_option (line 58) | def test_quiet_option(run, runner):
  function test_quiet_option_when_up_to_date (line 75) | def test_quiet_option_when_up_to_date(run, runner):
  function test_no_requirements_file (line 90) | def test_no_requirements_file(runner):
  function test_input_files_with_dot_in_extension (line 101) | def test_input_files_with_dot_in_extension(runner, tmp_path):
  function test_force_files_with_dot_in_extension (line 114) | def test_force_files_with_dot_in_extension(runner, tmp_path):
  function test_merge_error (line 139) | def test_merge_error(req_lines, should_raise, runner):
  function test_merge_no_name_urls (line 167) | def test_merge_no_name_urls(run, req_line, runner, tmp_path):
  function test_pip_install_flags (line 218) | def test_pip_install_flags(run, cli_flags, expected_install_flags, runner):
  function test_pip_install_flags_in_requirements_file (line 247) | def test_pip_install_flags_in_requirements_file(run, runner, install_fla...
  function test_sync_ask_declined (line 265) | def test_sync_ask_declined(run, runner):
  function test_sync_ask_accepted (line 278) | def test_sync_ask_accepted(run, runner):
  function test_sync_dry_run_returns_non_zero_exit_code (line 291) | def test_sync_dry_run_returns_non_zero_exit_code(runner):
  function test_python_executable_option (line 304) | def test_python_executable_option(
  function test_invalid_python_executable (line 340) | def test_invalid_python_executable(runner, python_executable):
  function test_invalid_pip_version_in_python_executable (line 351) | def test_invalid_pip_version_in_python_executable(
  function test_default_python_executable_option (line 376) | def test_default_python_executable_option(run, runner):
  function test_default_config_option (line 401) | def test_default_config_option(run, runner, make_config_file, tmpdir_cwd):
  function test_config_option (line 414) | def test_config_option(run, runner, make_config_file):
  function test_no_config_option_overrides_config_with_defaults (line 427) | def test_no_config_option_overrides_config_with_defaults(run, runner, ma...
  function test_raise_error_on_unknown_config_option (line 440) | def test_raise_error_on_unknown_config_option(run, runner, tmp_path, mak...
  function test_raise_error_on_invalid_config_option (line 453) | def test_raise_error_on_invalid_config_option(run, runner, tmp_path, mak...
  function test_allow_in_config_pip_compile_option (line 466) | def test_allow_in_config_pip_compile_option(run, runner, tmp_path, make_...
  function test_tool_specific_config_option (line 479) | def test_tool_specific_config_option(run, runner, make_config_file):

FILE: tests/test_data/packages/small_fake_with_build_deps/backend/backend.py
  function get_requires_for_build_sdist (line 15) | def get_requires_for_build_sdist(config_settings=None):
  function get_requires_for_build_wheel (line 23) | def get_requires_for_build_wheel(config_settings=None):
  function get_requires_for_build_editable (line 31) | def get_requires_for_build_editable(config_settings=None):

FILE: tests/test_fake_index.py
  function test_find_best_match (line 6) | def test_find_best_match(from_line, repository):
  function test_find_best_match_incl_prereleases (line 22) | def test_find_best_match_incl_prereleases(from_line, repository):
  function test_find_best_match_for_editable (line 32) | def test_find_best_match_for_editable(from_editable, repository):
  function test_get_dependencies (line 37) | def test_get_dependencies(from_line, repository):
  function test_get_dependencies_for_editable (line 74) | def test_get_dependencies_for_editable(from_editable, repository):
  function test_get_dependencies_rejects_non_pinned_requirements (line 79) | def test_get_dependencies_rejects_non_pinned_requirements(from_line, rep...
  function test_get_hashes (line 85) | def test_get_hashes(from_line, repository):

FILE: tests/test_logging.py
  function test_indentation (line 6) | def test_indentation(runner):

FILE: tests/test_minimal_upgrade.py
  function test_no_upgrades (line 37) | def test_no_upgrades(base_resolver, repository, from_line, input, pins, ...

FILE: tests/test_pip_compat.py
  function test_parse_requirements_preserve_editable_relative_path (line 10) | def test_parse_requirements_preserve_editable_relative_path(tmp_path, re...

FILE: tests/test_repository_local.py
  function test_get_hashes_local_repository_cache_miss (line 11) | def test_get_hashes_local_repository_cache_miss(
  function test_get_hashes_local_repository_cache_hit (line 24) | def test_get_hashes_local_repository_cache_hit(from_line, repository):
  function test_toggle_reuse_hashes_local_repository (line 43) | def test_toggle_reuse_hashes_local_repository(

FILE: tests/test_repository_pypi.py
  function test_generate_hashes_all_platforms (line 16) | def test_generate_hashes_all_platforms(capsys, pip_conf, from_line, pypi...
  function test_get_file_hash_without_interfering_with_each_other (line 39) | def test_get_file_hash_without_interfering_with_each_other(from_line, py...
  function test_get_hashes_editable_empty_set (line 71) | def test_get_hashes_editable_empty_set(from_editable, pypi_repository):
  function test_get_hashes_unpinned_raises (line 76) | def test_get_hashes_unpinned_raises(from_line, pypi_repository):
  function test_open_local_or_remote_file__local_file (line 85) | def test_open_local_or_remote_file__local_file(tmp_path, content, conten...
  function test_open_local_or_remote_file__directory (line 101) | def test_open_local_or_remote_file__directory(tmpdir):
  function test_open_local_or_remote_file__remote_file (line 120) | def test_open_local_or_remote_file__remote_file(
  function test_relative_path_cache_dir_is_normalized (line 146) | def test_relative_path_cache_dir_is_normalized(from_line):
  function test_relative_path_pip_cache_dir_is_normalized (line 154) | def test_relative_path_pip_cache_dir_is_normalized(from_line, tmpdir):
  function test_pip_cache_dir_is_empty (line 164) | def test_pip_cache_dir_is_empty(from_line, tmpdir):
  function test_get_hashes_from_pypi (line 273) | def test_get_hashes_from_pypi(from_line, tmpdir, project_data, expected_...
  function test_get_hashes_from_mixed (line 291) | def test_get_hashes_from_mixed(pip_conf, from_line, tmpdir):
  function test_get_project__returns_data (line 349) | def test_get_project__returns_data(from_line, tmpdir, monkeypatch, pypi_...
  function test_get_project__handles_http_error (line 372) | def test_get_project__handles_http_error(
  function test_get_project__handles_json_decode_error (line 389) | def test_get_project__handles_json_decode_error(
  function test_get_project__handles_404 (line 413) | def test_get_project__handles_404(from_line, tmpdir, monkeypatch, pypi_r...
  function test_name_collision (line 432) | def test_name_collision(from_line, pypi_repository, make_package, make_s...

FILE: tests/test_resolver.py
  function test_resolver (line 197) | def test_resolver(
  function test_resolver__allows_unsafe_deps (line 243) | def test_resolver__allows_unsafe_deps(
  function test_resolver__custom_unsafe_deps (line 281) | def test_resolver__custom_unsafe_deps(
  function test_resolver__max_number_rounds_reached (line 302) | def test_resolver__max_number_rounds_reached(resolver, from_line):
  function test_iter_dependencies (line 311) | def test_iter_dependencies(resolver, from_line):
  function test_iter_dependencies_results (line 324) | def test_iter_dependencies_results(resolver, from_line):
  function test_iter_dependencies_ignores_constraints (line 330) | def test_iter_dependencies_ignores_constraints(resolver, from_line):
  function test_iter_dependencies_after_combine_install_requirements (line 337) | def test_iter_dependencies_after_combine_install_requirements(
  function test_iter_dependencies_after_combine_install_requirements_extras (line 354) | def test_iter_dependencies_after_combine_install_requirements_extras(
  function test_combine_install_requirements (line 377) | def test_combine_install_requirements(from_line):
  function _test_combine_install_requirements_extras (line 393) | def _test_combine_install_requirements_extras(with_extra, without_extra):
  function test_combine_install_requirements_extras_req (line 403) | def test_combine_install_requirements_extras_req(from_line, make_package):
  function test_combine_install_requirements_extras_no_req (line 416) | def test_combine_install_requirements_extras_no_req(from_line, make_pack...
  function test_combine_install_requirements_with_paths (line 432) | def test_combine_install_requirements_with_paths(from_line, make_package):
  function test_combine_install_requirements_for_one_package_with_multiple_extras (line 448) | def test_combine_install_requirements_for_one_package_with_multiple_extras(
  function test_compile_failure_shows_provenance (line 459) | def test_compile_failure_shows_provenance(resolver, from_line):
  function test_RequirementSummary_equality (line 503) | def test_RequirementSummary_equality(from_line, left_hand, right_hand, e...
  function test_RequirementSummary_hash_equality (line 537) | def test_RequirementSummary_hash_equality(from_line, left_hand, right_ha...
  function test_requirement_summary_with_other_objects (line 546) | def test_requirement_summary_with_other_objects(from_line):
  function test_catch_distribution_not_found_error (line 562) | def test_catch_distribution_not_found_error(backtracking_resolver, excep...

FILE: tests/test_sync.py
  function mocked_tmp_file (line 20) | def mocked_tmp_file():
  function mocked_tmp_req_file (line 26) | def mocked_tmp_req_file(mocked_tmp_file):
  function test_dependency_tree (line 69) | def test_dependency_tree(fake_dist, installed, root, expected):
  function test_merge_detect_conflicts (line 79) | def test_merge_detect_conflicts(from_line):
  function test_merge_ignore_conflicts (line 86) | def test_merge_ignore_conflicts(from_line):
  function test_merge (line 94) | def test_merge(from_line):
  function test_merge_urls (line 106) | def test_merge_urls(from_line):
  function test_merge_no_name_urls (line 125) | def test_merge_no_name_urls(install_req, request):
  function test_diff_should_do_nothing (line 138) | def test_diff_should_do_nothing():
  function test_diff_should_install (line 147) | def test_diff_should_install(from_line):
  function test_diff_should_uninstall (line 156) | def test_diff_should_uninstall(fake_dist):
  function test_diff_should_not_uninstall (line 165) | def test_diff_should_not_uninstall(fake_dist):
  function test_diff_should_update (line 191) | def test_diff_should_update(fake_dist, from_line):
  function test_diff_should_install_with_markers (line 200) | def test_diff_should_install_with_markers(from_line):
  function test_diff_should_uninstall_with_markers (line 209) | def test_diff_should_uninstall_with_markers(fake_dist, from_line):
  function test_diff_leave_packaging_packages_alone (line 218) | def test_diff_leave_packaging_packages_alone(fake_dist, from_line):
  function test_diff_leave_piptools_and_its_dependencies_alone (line 235) | def test_diff_leave_piptools_and_its_dependencies_alone(fake_dist, from_...
  function test_diff_with_editable (line 258) | def test_diff_with_editable(fake_dist, from_editable):
  function test_diff_with_matching_url_hash (line 274) | def test_diff_with_matching_url_hash(fake_dist, from_line):
  function test_diff_respects_canonical_package_names (line 296) | def test_diff_respects_canonical_package_names(
  function test_diff_with_no_url_hash (line 306) | def test_diff_with_no_url_hash(fake_dist, from_line):
  function test_diff_with_unequal_url_hash (line 318) | def test_diff_with_unequal_url_hash(fake_dist, from_line):
  function test_sync_install_temporary_requirement_file (line 330) | def test_sync_install_temporary_requirement_file(
  function test_temporary_requirement_file_deleted (line 342) | def test_temporary_requirement_file_deleted(from_line, from_editable, mo...
  function test_sync_requirement_file (line 352) | def test_sync_requirement_file(from_line, from_editable, mocked_tmp_req_...
  function test_sync_requirement_file_with_hashes (line 374) | def test_sync_requirement_file_with_hashes(
  function test_sync_up_to_date (line 428) | def test_sync_up_to_date(capsys, runner):
  function test_sync_verbose (line 439) | def test_sync_verbose(run, from_line):
  function test_sync_dry_run (line 457) | def test_sync_dry_run(
  function test_sync_ask_declined (line 482) | def test_sync_ask_declined(
  function test_sync_ask_accepted (line 506) | def test_sync_ask_accepted(run, monkeypatch, capsys, from_line, dry_run):
  function test_sync_uninstall_pip_command (line 531) | def test_sync_uninstall_pip_command(run):

FILE: tests/test_utils.py
  function test_format_requirement (line 40) | def test_format_requirement(from_line):
  function test_format_requirement_url (line 139) | def test_format_requirement_url(from_line, line, expected):
  function test_format_requirement_editable_vcs (line 144) | def test_format_requirement_editable_vcs(from_editable):
  function test_format_requirement_editable_vcs_with_password (line 149) | def test_format_requirement_editable_vcs_with_password(from_editable):
  function test_format_requirement_editable_local_path (line 156) | def test_format_requirement_editable_local_path(from_editable):
  function test_format_requirement_ireq_with_hashes (line 161) | def test_format_requirement_ireq_with_hashes(from_line):
  function test_format_requirement_ireq_with_hashes_and_markers (line 178) | def test_format_requirement_ireq_with_hashes_and_markers(from_line):
  function test_format_specifier (line 196) | def test_format_specifier(from_line, from_editable):
  function test_as_tuple (line 214) | def test_as_tuple(from_line):
  function test_flat_map (line 235) | def test_flat_map():
  function test_dedup (line 239) | def test_dedup():
  function test_get_hashes_from_ireq (line 243) | def test_get_hashes_from_ireq(from_line):
  function test_is_pinned_requirement (line 272) | def test_is_pinned_requirement(from_line, line, expected):
  function test_is_pinned_requirement_editable (line 277) | def test_is_pinned_requirement_editable(from_editable):
  function test_key_from_ireq_normalization (line 282) | def test_key_from_ireq_normalization(from_line):
  function test_key_from_req_on_install_requirement (line 298) | def test_key_from_req_on_install_requirement(
  function test_key_from_req_on_specifier_requirement (line 318) | def test_key_from_req_on_specifier_requirement(
  function test_is_url_requirement (line 340) | def test_is_url_requirement(caplog, from_line, line, expected):
  function test_is_url_requirement_filename (line 346) | def test_is_url_requirement_filename(caplog, from_line, line):
  function test_get_compile_command (line 431) | def test_get_compile_command(tmpdir_cwd, cli_args, expected_command):
  function test_get_compile_command_with_config (line 455) | def test_get_compile_command_with_config(tmpdir_cwd, config_file, expect...
  function test_get_compile_command_does_not_include_default_config_if_reqs_file_in_subdir (line 472) | def test_get_compile_command_does_not_include_default_config_if_reqs_fil...
  function test_get_compile_command_escaped_filenames (line 493) | def test_get_compile_command_escaped_filenames(tmpdir_cwd):
  function test_get_compile_command_with_files (line 506) | def test_get_compile_command_with_files(tmpdir_cwd, filename):
  function test_get_compile_command_sort_args (line 525) | def test_get_compile_command_sort_args(tmpdir_cwd):
  function test_lookup_table_from_tuples (line 560) | def test_lookup_table_from_tuples(tuples):
  function test_lookup_table (line 572) | def test_lookup_table(values, key):
  function test_lookup_table_from_tuples_with_empty_values (line 577) | def test_lookup_table_from_tuples_with_empty_values():
  function test_lookup_table_with_empty_values (line 581) | def test_lookup_table_with_empty_values():
  function test_drop_extras (line 631) | def test_drop_extras(from_line, given, expected):
  function test_get_sys_path_for_python_executable (line 640) | def test_get_sys_path_for_python_executable():
  function test_callback_config_file_defaults (line 688) | def test_callback_config_file_defaults(pyproject_param, new_default, mak...
  function test_callback_config_file_defaults_multi_validate_value (line 715) | def test_callback_config_file_defaults_multi_validate_value(
  function test_callback_config_file_defaults_bad_toml (line 725) | def test_callback_config_file_defaults_bad_toml(make_config_file):
  function test_callback_config_file_defaults_precedence (line 737) | def test_callback_config_file_defaults_precedence(make_config_file):
  function test_callback_config_file_defaults_unreadable_toml (line 748) | def test_callback_config_file_defaults_unreadable_toml(make_config_file):
  function test_select_config_file_no_files (line 758) | def test_select_config_file_no_files(tmpdir_cwd):
  function test_select_config_file_returns_config_in_cwd (line 763) | def test_select_config_file_returns_config_in_cwd(make_config_file, file...
  function test_select_config_file_returns_empty_config_file_in_cwd (line 768) | def test_select_config_file_returns_empty_config_file_in_cwd(tmpdir_cwd):
  function test_select_config_file_cannot_find_config_in_cwd (line 775) | def test_select_config_file_cannot_find_config_in_cwd(tmpdir_cwd, make_c...
  function test_select_config_file_with_config_file_in_subdir (line 780) | def test_select_config_file_with_config_file_in_subdir(tmpdir_cwd, make_...
  function test_select_config_file_prefers_pip_tools_toml_over_pyproject_toml (line 789) | def test_select_config_file_prefers_pip_tools_toml_over_pyproject_toml(t...

FILE: tests/test_writer.py
  function writer (line 20) | def writer(tmpdir_cwd):
  function test_format_requirement_annotation_editable (line 57) | def test_format_requirement_annotation_editable(from_editable, writer):
  function test_format_requirement_annotation (line 67) | def test_format_requirement_annotation(from_line, writer):
  function test_format_requirement_annotation_lower_case (line 74) | def test_format_requirement_annotation_lower_case(from_line, writer):
  function test_format_requirement_for_primary (line 81) | def test_format_requirement_for_primary(from_line, writer):
  function test_format_requirement_for_primary_lower_case (line 89) | def test_format_requirement_for_primary_lower_case(from_line, writer):
  function test_format_requirement_environment_marker (line 97) | def test_format_requirement_environment_marker(from_line, writer):
  function test_iter_lines__unsafe_dependencies (line 111) | def test_iter_lines__unsafe_dependencies(writer, from_line, allow_unsafe):
  function test_iter_lines__unsafe_with_hashes (line 131) | def test_iter_lines__unsafe_with_hashes(capsys, writer, from_line):
  function test_iter_lines__hash_missing (line 154) | def test_iter_lines__hash_missing(capsys, writer, from_line):
  function test_iter_lines__no_warn_if_only_unhashable_packages (line 179) | def test_iter_lines__no_warn_if_only_unhashable_packages(writer, from_li...
  function test_write_header (line 207) | def test_write_header(writer):
  function test_write_header_custom_compile_command (line 225) | def test_write_header_custom_compile_command(writer, monkeypatch):
  function test_write_header_no_emit_header (line 242) | def test_write_header_no_emit_header(writer):
  function test_write_flags_emit_options (line 270) | def test_write_flags_emit_options(writer, emit_options, expected_flags):
  function test_write_format_controls (line 283) | def test_write_format_controls(writer):
  function test_write_format_controls_all (line 325) | def test_write_format_controls_all(writer, no_binary, only_binary, expec...
  function test_write_index_options (line 402) | def test_write_index_options(writer, index_urls, expected_lines):
  function test_write_index_options_no_emit_index (line 411) | def test_write_index_options_no_emit_index(writer):
  function test_write_find_links (line 429) | def test_write_find_links(writer, find_links, expected_lines):
  function test_write_order (line 437) | def test_write_order(writer, from_line):

FILE: tests/unit/_internal/pip_api/test_cli_options.py
  function test_postprocess_cli_options_pre_adds_all_to_release_control_all_releases (line 12) | def test_postprocess_cli_options_pre_adds_all_to_release_control_all_rel...

FILE: tests/unit/_internal/pip_api/test_install_requirements.py
  function test_copy_install_requirement_removes_pip_25_3_unsupported_opts (line 12) | def test_copy_install_requirement_removes_pip_25_3_unsupported_opts(use_...
  function test_copy_install_requirement_preserves_pip_25_3_unsupported_opts (line 23) | def test_copy_install_requirement_preserves_pip_25_3_unsupported_opts(us...

FILE: tests/unit/_internal/pip_api/test_package_finder.py
  function finder_with_pre (line 10) | def finder_with_pre(tmp_path):
  function test_finder_with_pre_allows_all_prereleases (line 17) | def test_finder_with_pre_allows_all_prereleases(finder_with_pre):
  function test_finder_with_pre_allows_specific_package_prereleases (line 21) | def test_finder_with_pre_allows_specific_package_prereleases(finder_with...

FILE: tests/unit/_internal/pip_api/test_pip_version.py
  function test_get_pip_version_for_python_executable (line 11) | def test_get_pip_version_for_python_executable():

FILE: tests/unit/_internal/test_subprocess.py
  function test_run_python_snippet_returns_multilne (line 8) | def test_run_python_snippet_returns_multilne():

FILE: tests/utils.py
  function looks_like_ci (line 9) | def looks_like_ci():
Condensed preview — 140 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (672K chars).
[
  {
    "path": ".bandit",
    "chars": 58,
    "preview": "[bandit]\nexclude: tests,.tox,.eggs,.venv,.git\nskips: B101\n"
  },
  {
    "path": ".codecov.yml",
    "chars": 173,
    "preview": "---\n\ncodecov:\n  notify:\n    manual_trigger: true  # prevent notifications until we notify Codecov\n\n  require_ci_to_pass:"
  },
  {
    "path": ".coveragerc",
    "chars": 114,
    "preview": "[run]\nplugins = covdefaults\nomit =\n    piptools/_compat/*\n\n[report]\ninclude = piptools/*, tests/*\nfail_under = 99\n"
  },
  {
    "path": ".flake8",
    "chars": 432,
    "preview": "[flake8]\nmax-line-length = 100\n# E203 conflicts with PEP8; see https://github.com/psf/black#slices\nextend-ignore = E203\n"
  },
  {
    "path": ".git_archival.txt",
    "chars": 107,
    "preview": "node: $Format:%H$\nnode-date: $Format:%cI$\ndescribe-name: $Format:%(describe:tags=true,match=v[0-9]*[0-9])$\n"
  },
  {
    "path": ".gitattributes",
    "chars": 106,
    "preview": "# fill in placeholders when `git archive` is used, setuptools-scm support\n.git_archival.txt  export-subst\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 71,
    "preview": "/.github/ @jazzband/pip-tools-leads\n/tox.ini @jazzband/pip-tools-leads\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 365,
    "preview": "---\n\nname: Bug report\nabout: Create a report to help us improve\n\n---\n\n<!-- Describe the issue briefly here. -->\n\n#### En"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "chars": 734,
    "preview": "---\n\nname: Feature request\nabout: Suggest an idea for this project\n\n---\n\n#### What's the problem this feature will solve"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 567,
    "preview": "<!--- Describe the changes here. --->\n\n##### Contributor checklist\n\n- [ ] Included tests for the changes.\n- [ ] A change"
  },
  {
    "path": ".github/actions/cache-keys/action.yml",
    "chars": 1109,
    "preview": "---\n\nname: placeholder\ndescription: placeholder\n\noutputs:\n  cache-key-for-dep-files:\n    description: >-\n      A cache k"
  },
  {
    "path": ".github/chronographer.yml",
    "chars": 448,
    "preview": "branch-protection-check-name: Change log entry\naction-hints:\n  check-title-prefix: \"Chronographer: \"\n  external-docs-url"
  },
  {
    "path": ".github/reusables/tox-dev/workflow/reusable-tox/hooks/post-tox-run/action.yml",
    "chars": 2334,
    "preview": "---\n\ninputs:\n  calling-job-context:\n    description: A JSON with the calling job inputs\n    type: string\n  current-job-s"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 17707,
    "preview": "name: CI\n\non:\n  merge_group:\n  pull_request:\n  push:\n    branches:\n      - main\n    tags:\n      - v*\n  workflow_call:\n  "
  },
  {
    "path": ".github/workflows/cron.yml",
    "chars": 323,
    "preview": "name: Cron\n\non:\n  schedule:\n    # Run everyday at 03:53 UTC\n    - cron: 53 3 * * *\n\njobs:\n  main:\n    name: CI\n    uses:"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 3225,
    "preview": "---\nname: 📦 Packaging\n\non:\n  release:\n    types:\n      - published\n\nenv:\n  FORCE_COLOR: 1 # Request colored output from "
  },
  {
    "path": ".github/workflows/reusable-qa.yml",
    "chars": 1777,
    "preview": "name: QA\n\non:\n  workflow_call:\n\njobs:\n  qa:\n    name: ${{ matrix.toxenv }}\n    runs-on: ubuntu-latest\n    timeout-minute"
  },
  {
    "path": ".gitignore",
    "chars": 284,
    "preview": "# Ignore cram test output\n*.t.err\n\n# Python cruft\n*.pyc\n\n# Virtualenvs\n.envrc\n.direnv\n.venv\nvenv/\n\n# Testing\n.pytest_cac"
  },
  {
    "path": ".pre-commit-config.yaml",
    "chars": 5751,
    "preview": "repos:\n  - repo: https://github.com/psf/black-pre-commit-mirror\n    rev: 26.3.1\n    hooks:\n      - id: black\n        arg"
  },
  {
    "path": ".pre-commit-hooks.yaml",
    "chars": 187,
    "preview": "- id: pip-compile\n  name: pip-compile\n  description: Automatically compile requirements.\n  entry: pip-compile\n  language"
  },
  {
    "path": ".pymarkdown.yml",
    "chars": 13,
    "preview": "---\n\n{}\n\n...\n"
  },
  {
    "path": ".readthedocs.yaml",
    "chars": 845,
    "preview": "# https://docs.readthedocs.io/en/stable/config-file/v2.html\n\nversion: 2\n\nbuild:\n  os: ubuntu-24.04\n\n  # in order to have"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 47583,
    "preview": "# Change log\n\n<!-- towncrier release notes start -->\n\n## v7.5.3\n\n*2026-02-09*\n\n### Bug fixes\n\n- The option `--unsafe-pac"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 2375,
    "preview": "# Code of Conduct\n\nAs contributors and maintainers of the Jazzband projects, and in the interest\nof fostering an open an"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 4807,
    "preview": "# Contributing to `pip-tools`\n\n<!-- sphinx-inclusion-post-this-line -->\n\n[![Jazzband](https://jazzband.co/static/img/jaz"
  },
  {
    "path": "LICENSE",
    "chars": 1522,
    "preview": "BSD 3-Clause License\n\nCopyright (c). All rights reserved.\n\nRedistribution and use in source and binary forms, with or wi"
  },
  {
    "path": "MANIFEST.in",
    "chars": 165,
    "preview": "# do not include the `.git_archival.txt` file in sdist builds from repo source\n# this avoids setuptools-scm warnings on "
  },
  {
    "path": "README.md",
    "chars": 25192,
    "preview": "<!-- pyml disable-next-line first-line-heading -->\n[![jazzband-image]][jazzband]\n[![pypi][pypi-image]][pypi]\n[![pyversio"
  },
  {
    "path": "changelog.d/.draft_changelog_partial.md",
    "chars": 47,
    "preview": "```{towncrier-draft-entries}\nDRAFT_VERSION\n```\n"
  },
  {
    "path": "changelog.d/.gitignore",
    "chars": 506,
    "preview": "*\n!.gitignore\n!.towncrier_template.md.jinja\n!.draft_changelog_partial.md\n!README.md\n!*.afterword\n!*.afterword.md\n!*.afte"
  },
  {
    "path": "changelog.d/.towncrier_template.md.jinja",
    "chars": 2099,
    "preview": "{%- set is_draft_preview = versiondata[\"version\"] == \"DRAFT_VERSION\" -%}\n{%- set special_category_admonitions = {\n  'aft"
  },
  {
    "path": "changelog.d/1142.feature.md",
    "chars": 112,
    "preview": "Add usage examples to the ``--help`` output for ``pip-compile`` and\n``pip-sync`` commands.\n\n-- by {user}`Dzhud`\n"
  },
  {
    "path": "changelog.d/2318.contrib.md",
    "chars": 386,
    "preview": "`pip-tools` now has a policy regarding LLM-generated contributions, noted in the\ncontributing documentation -- by {user}"
  },
  {
    "path": "changelog.d/2327.contrib.md",
    "chars": 142,
    "preview": "Started running {pypi}`zizmor` as a part of CI pipelines to improve\nsecurity of how we configure GitHub Actions CI/CD\n--"
  },
  {
    "path": "changelog.d/2343.contrib.md",
    "chars": 94,
    "preview": "pip-tools docs now support GitHub Flavored Markdown admonition blocks\n-- by {user}`webknjaz`.\n"
  },
  {
    "path": "changelog.d/README.md",
    "chars": 5041,
    "preview": "# How this folder is managed\n\n<!-- sphinx-inclusion-post-this-line -->\n\n## Adding Change Notes with PRs\n\nIt is important"
  },
  {
    "path": "docs/.gitignore",
    "chars": 35,
    "preview": "!requirements.in\n!requirements.txt\n"
  },
  {
    "path": "docs/changelog.md",
    "chars": 710,
    "preview": "# Changelog\n\n```{eval-rst}\n\n.. MyST doesn't support the \"only\" directive correctly. It always evaluates to\n.. true.\n..\n."
  },
  {
    "path": "docs/cli/index.md",
    "chars": 160,
    "preview": "# Command Line Reference\n\nThis page provides a reference for the `pip-tools` command-line interface (CLI):\n\n```{toctree}"
  },
  {
    "path": "docs/cli/pip-compile.md",
    "chars": 59,
    "preview": "# pip-compile\n\n```{program-output} pip-compile --help\n\n```\n"
  },
  {
    "path": "docs/cli/pip-sync.md",
    "chars": 53,
    "preview": "# pip-sync\n\n```{program-output} pip-sync --help\n\n```\n"
  },
  {
    "path": "docs/conf.py",
    "chars": 4559,
    "preview": "# https://www.sphinx-doc.org/en/master/usage/configuration.html\n\"\"\"Configuration file for the Sphinx documentation build"
  },
  {
    "path": "docs/contributing.md",
    "chars": 205,
    "preview": "# Contributing\n\n```{include} ../CONTRIBUTING.md\n:start-after: <!-- sphinx-inclusion-post-this-line -->\n```\n\n```{include}"
  },
  {
    "path": "docs/index.md",
    "chars": 292,
    "preview": "<!-- pyml disable-next-line no-trailing-punctuation -->\n# Welcome to pip-tools' documentation!\n\n```{include} ../README.m"
  },
  {
    "path": "docs/pkg/.gitignore",
    "chars": 14,
    "preview": "*\n!.gitignore\n"
  },
  {
    "path": "docs/requirements.in",
    "chars": 261,
    "preview": "click-extra [sphinx]  # GitHub-flavored admonitions: https://github.com/executablebooks/MyST-Parser/issues/845#issuecomm"
  },
  {
    "path": "docs/requirements.txt",
    "chars": 3423,
    "preview": "#\n# This file is autogenerated by pip-compile with Python 3.12\n# by the following command:\n#\n#    pip-compile --allow-un"
  },
  {
    "path": "examples/django.in",
    "chars": 134,
    "preview": "# This file includes the Django project, and the debug toolbar\nDjango<2.2.1   # suppose some version requirement\ndjango-"
  },
  {
    "path": "examples/flask.in",
    "chars": 49,
    "preview": "# Flask has 2nd and 3rd level dependencies\nFlask\n"
  },
  {
    "path": "examples/hypothesis.in",
    "chars": 19,
    "preview": "hypothesis[django]\n"
  },
  {
    "path": "examples/protection.in",
    "chars": 168,
    "preview": "# This package depends on setuptools, which should not end up in the compiled\n# requirements, because it may cause confl"
  },
  {
    "path": "examples/readme/constraints.txt",
    "chars": 846,
    "preview": "#\n# This file is autogenerated by pip-compile with Python 3.11\n# by the following command:\n#\n#    pip-compile --all-buil"
  },
  {
    "path": "examples/readme/pyproject.toml",
    "chars": 204,
    "preview": "[build-system]\nrequires = [\"hatchling\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"my-cool-django-app\"\nversion"
  },
  {
    "path": "examples/sentry.in",
    "chars": 49,
    "preview": "# Sentry has a very large dependency tree\nsentry\n"
  },
  {
    "path": "piptools/__init__.py",
    "chars": 398,
    "preview": "from __future__ import annotations\n\nimport locale\n\nfrom click import secho\n\n# Needed for locale.getpreferredencoding(Fal"
  },
  {
    "path": "piptools/__main__.py",
    "chars": 290,
    "preview": "from __future__ import annotations\n\nimport click\n\nfrom piptools.scripts import compile, sync\n\n\n@click.group()\ndef cli() "
  },
  {
    "path": "piptools/_compat/__init__.py",
    "chars": 303,
    "preview": "from __future__ import annotations\n\nfrom .pip_compat import (\n    Distribution,\n    canonicalize_name,\n    create_wheel_"
  },
  {
    "path": "piptools/_compat/_tomllib_compat.py",
    "chars": 239,
    "preview": "from __future__ import annotations\n\nimport sys\n\nif sys.version_info >= (3, 11):\n    from tomllib import TOMLDecodeError,"
  },
  {
    "path": "piptools/_compat/path_compat.py",
    "chars": 795,
    "preview": "\"\"\"\nCompatibility helpers for working with paths and :mod:`pathlib` across platforms\nand Python versions.\n\"\"\"\n\nfrom __fu"
  },
  {
    "path": "piptools/_compat/pip_compat.py",
    "chars": 8223,
    "preview": "from __future__ import annotations\n\nimport optparse\nimport pathlib\nimport typing as _t\nimport urllib.parse\nfrom collecti"
  },
  {
    "path": "piptools/_compat/tempfile_compat.py",
    "chars": 822,
    "preview": "\"\"\"\nCompatibility helpers for :mod:`tempfile` usage across platforms\nand python versions.\n\"\"\"\n\nfrom __future__ import an"
  },
  {
    "path": "piptools/_internal/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "piptools/_internal/_pip_api/__init__.py",
    "chars": 994,
    "preview": "\"\"\"\nThe ``piptools._pip_api`` subpackage defines an API layer on top of ``pip`` internals\nand usage. It is a private API"
  },
  {
    "path": "piptools/_internal/_pip_api/cli_options.py",
    "chars": 529,
    "preview": "\"\"\"\nTools for parsing pip CLI options.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport optparse\n\nfrom pip._internal.cli "
  },
  {
    "path": "piptools/_internal/_pip_api/install_requirements.py",
    "chars": 3258,
    "preview": "from __future__ import annotations\n\nimport copy\nimport typing as _t\n\nfrom pip._internal.req import InstallRequirement\nfr"
  },
  {
    "path": "piptools/_internal/_pip_api/package_finder.py",
    "chars": 1458,
    "preview": "\"\"\"\nPackageFinder interfaces for pip-tools.\n\nBecause the PackageFinder class itself has evolved over pip's lifetime, the"
  },
  {
    "path": "piptools/_internal/_pip_api/pip_version.py",
    "chars": 720,
    "preview": "from __future__ import annotations\n\nimport pip\nfrom pip._vendor.packaging.version import Version\nfrom pip._vendor.packag"
  },
  {
    "path": "piptools/_internal/_subprocess.py",
    "chars": 581,
    "preview": "# WARNING! BE CAREFUL UPDATING THIS FILE\n# Consider possible security implications associated with subprocess module.\nfr"
  },
  {
    "path": "piptools/build.py",
    "chars": 12514,
    "preview": "from __future__ import annotations\n\nimport collections\nimport contextlib\nimport os\nimport pathlib\nimport sys\nimport temp"
  },
  {
    "path": "piptools/cache.py",
    "chars": 6112,
    "preview": "from __future__ import annotations\n\nimport json\nimport os\nimport platform\nimport sys\nimport typing as _t\nfrom collection"
  },
  {
    "path": "piptools/exceptions.py",
    "chars": 2607,
    "preview": "from __future__ import annotations\n\nimport operator\nfrom collections.abc import Iterable\n\nfrom pip._internal.index.packa"
  },
  {
    "path": "piptools/locations.py",
    "chars": 339,
    "preview": "from __future__ import annotations\n\nfrom pip._internal.utils.appdirs import user_cache_dir\n\n# The user_cache_dir helper "
  },
  {
    "path": "piptools/logging.py",
    "chars": 2044,
    "preview": "from __future__ import annotations\n\nimport contextlib\nimport logging\nimport sys\nimport typing as _t\nfrom collections.abc"
  },
  {
    "path": "piptools/py.typed",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "piptools/repositories/__init__.py",
    "chars": 177,
    "preview": "from __future__ import annotations\n\nfrom .local import LocalRequirementsRepository\nfrom .pypi import PyPIRepository\n\n__a"
  },
  {
    "path": "piptools/repositories/base.py",
    "chars": 2367,
    "preview": "from __future__ import annotations\n\nimport optparse\nfrom abc import ABCMeta, abstractmethod\nfrom collections.abc import "
  },
  {
    "path": "piptools/repositories/local.py",
    "chars": 3749,
    "preview": "from __future__ import annotations\n\nimport optparse\nimport typing as _t\nfrom collections.abc import Iterator, Mapping\nfr"
  },
  {
    "path": "piptools/repositories/pypi.py",
    "chars": 20146,
    "preview": "from __future__ import annotations\n\nimport contextlib\nimport hashlib\nimport itertools\nimport optparse\nimport os\nimport t"
  },
  {
    "path": "piptools/resolver.py",
    "chars": 32034,
    "preview": "from __future__ import annotations\n\nimport collections\nimport copy\nimport typing as _t\nfrom abc import ABCMeta, abstract"
  },
  {
    "path": "piptools/scripts/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "piptools/scripts/_deprecations.py",
    "chars": 1482,
    "preview": "\"\"\"Module to deprecate script arguments.\"\"\"\n\nfrom __future__ import annotations\n\nfrom .._internal import _pip_api\nfrom ."
  },
  {
    "path": "piptools/scripts/compile.py",
    "chars": 18861,
    "preview": "from __future__ import annotations\n\nimport itertools\nimport os\nimport shlex\nimport sys\nimport typing as _t\nfrom pathlib "
  },
  {
    "path": "piptools/scripts/options.py",
    "chars": 10856,
    "preview": "from __future__ import annotations\n\nimport typing as _t\n\nimport click\nfrom pip._internal.commands import create_command\n"
  },
  {
    "path": "piptools/scripts/sync.py",
    "chars": 8104,
    "preview": "from __future__ import annotations\n\nimport itertools\nimport os\nimport shlex\nimport shutil\nimport sys\nimport typing as _t"
  },
  {
    "path": "piptools/sync.py",
    "chars": 8981,
    "preview": "from __future__ import annotations\n\nimport collections\nimport os\nimport sys\nimport tempfile\nfrom collections.abc import "
  },
  {
    "path": "piptools/utils.py",
    "chars": 22378,
    "preview": "from __future__ import annotations\n\nimport collections\nimport copy\nimport difflib\nimport itertools\nimport json\nimport os"
  },
  {
    "path": "piptools/writer.py",
    "chars": 12777,
    "preview": "from __future__ import annotations\n\nimport contextlib\nimport io\nimport os\nimport re\nimport sys\nimport types\nimport typin"
  },
  {
    "path": "pyproject.toml",
    "chars": 3943,
    "preview": "[build-system]\nrequires = [\"setuptools>=63\", \"setuptools_scm[toml]>=7\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[projec"
  },
  {
    "path": "tests/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/conftest.py",
    "chars": 16179,
    "preview": "from __future__ import annotations\n\nimport json\nimport os\nimport platform\nimport shutil\nimport subprocess\nimport sys\nimp"
  },
  {
    "path": "tests/constants.py",
    "chars": 355,
    "preview": "from __future__ import annotations\n\nimport os\n\nTEST_DATA_PATH = os.path.join(os.path.dirname(__file__), \"test_data\")\nMIN"
  },
  {
    "path": "tests/test_build.py",
    "chars": 7325,
    "preview": "from __future__ import annotations\n\nimport pathlib\nimport shutil\nimport textwrap\n\nimport pytest\nfrom build import BuildB"
  },
  {
    "path": "tests/test_cache.py",
    "chars": 3744,
    "preview": "from __future__ import annotations\n\nimport os\nimport sys\nfrom contextlib import contextmanager\nfrom shutil import rmtree"
  },
  {
    "path": "tests/test_circular_imports.py",
    "chars": 3615,
    "preview": "\"\"\"Tests for circular imports in all local packages and modules.\n\nThis ensures all internal packages can be imported rig"
  },
  {
    "path": "tests/test_cli_compile.py",
    "chars": 134068,
    "preview": "from __future__ import annotations\n\nimport dataclasses\nimport hashlib\nimport os\nimport pathlib\nimport re\nimport shlex\nim"
  },
  {
    "path": "tests/test_cli_sync.py",
    "chars": 15296,
    "preview": "from __future__ import annotations\n\nimport os\nimport subprocess\nimport sys\nfrom unittest import mock\n\nimport pytest\nfrom"
  },
  {
    "path": "tests/test_data/fake-editables.json",
    "chars": 117,
    "preview": "{\n  \"git+git://example.org/django.git#egg=django\": [],\n  \"git+https://github.com/celery/billiard#egg=billiard\": []\n}\n"
  },
  {
    "path": "tests/test_data/fake-index.json",
    "chars": 2749,
    "preview": "{\n  \"aiohttp\": {\n    \"3.6.2\": { \"\": [\"yarl\"] }\n  },\n  \"anyjson\": {\n    \"0.3.3\": { \"\": [] }\n  },\n  \"amqp\": {\n    \"1.4.9\":"
  },
  {
    "path": "tests/test_data/packages/fake_with_deps/fake_with_deps/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/test_data/packages/fake_with_deps/pyproject.toml",
    "chars": 730,
    "preview": "[build-system]\nrequires = [\"setuptools\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"fake_with_deps\"\ndesc"
  },
  {
    "path": "tests/test_data/packages/small_fake_a/setup.py",
    "chars": 106,
    "preview": "from __future__ import annotations\n\nfrom setuptools import setup\n\nsetup(name=\"small_fake_a\", version=0.1)\n"
  },
  {
    "path": "tests/test_data/packages/small_fake_with_build_deps/backend/backend.py",
    "chars": 1206,
    "preview": "from __future__ import annotations\n\n# A dependency of the build backend that is not installed is equivalent to a build\n#"
  },
  {
    "path": "tests/test_data/packages/small_fake_with_build_deps/pyproject.toml",
    "chars": 158,
    "preview": "[build-system]\nrequires = [\n    \"setuptools==68.1.2\",\n    \"wheel==0.41.1\",\n    \"fake_static_build_dep\"\n]\nbuild-backend ="
  },
  {
    "path": "tests/test_data/packages/small_fake_with_build_deps/setup.py",
    "chars": 272,
    "preview": "from __future__ import annotations\n\nfrom setuptools import setup\n\nsetup(\n    name=\"small_fake_with_build_deps\",\n    vers"
  },
  {
    "path": "tests/test_data/packages/small_fake_with_deps/setup.py",
    "chars": 190,
    "preview": "from __future__ import annotations\n\nfrom setuptools import setup\n\nsetup(\n    name=\"small_fake_with_deps\",\n    version=0."
  },
  {
    "path": "tests/test_data/packages/small_fake_with_deps_and_sub_deps/setup.py",
    "chars": 194,
    "preview": "from __future__ import annotations\n\nfrom setuptools import setup\n\nsetup(\n    name=\"small_fake_with_deps_and_sub_deps\",\n "
  },
  {
    "path": "tests/test_data/packages/small_fake_with_pyproject/pyproject.toml",
    "chars": 193,
    "preview": "[project]\nname=\"small_fake_with_pyproject\"\nversion=0.1\ndependencies=[\n    \"fake_direct_runtime_dep\",\n]\n[project.optional"
  },
  {
    "path": "tests/test_data/packages/small_fake_with_subdir/subdir/setup.py",
    "chars": 106,
    "preview": "from __future__ import annotations\n\nfrom setuptools import setup\n\nsetup(name=\"small_fake_a\", version=0.1)\n"
  },
  {
    "path": "tests/test_data/packages/small_fake_with_unpinned_deps/setup.py",
    "chars": 189,
    "preview": "from __future__ import annotations\n\nfrom setuptools import setup\n\nsetup(\n    name=\"small_fake_with_unpinned_deps\",\n    v"
  },
  {
    "path": "tests/test_fake_index.py",
    "chars": 2933,
    "preview": "from __future__ import annotations\n\nimport pytest\n\n\ndef test_find_best_match(from_line, repository):\n    ireq = from_lin"
  },
  {
    "path": "tests/test_logging.py",
    "chars": 771,
    "preview": "from __future__ import annotations\n\nfrom piptools.logging import LogContext\n\n\ndef test_indentation(runner):\n    \"\"\"\n    "
  },
  {
    "path": "tests/test_minimal_upgrade.py",
    "chars": 1646,
    "preview": "from __future__ import annotations\n\nimport pytest\n\nfrom piptools.repositories import LocalRequirementsRepository\nfrom pi"
  },
  {
    "path": "tests/test_pip_compat.py",
    "chars": 803,
    "preview": "from __future__ import annotations\n\nfrom pathlib import Path, PurePosixPath\n\nfrom piptools._compat.pip_compat import par"
  },
  {
    "path": "tests/test_repository_local.py",
    "chars": 2234,
    "preview": "from __future__ import annotations\n\nimport pytest\n\nfrom piptools.repositories.local import LocalRequirementsRepository\nf"
  },
  {
    "path": "tests/test_repository_pypi.py",
    "chars": 15879,
    "preview": "from __future__ import annotations\n\nimport os\nfrom unittest import mock\n\nimport pytest\nfrom pip._internal.models.candida"
  },
  {
    "path": "tests/test_resolver.py",
    "chars": 23739,
    "preview": "from __future__ import annotations\n\nimport pytest\nfrom pip._internal.exceptions import DistributionNotFound\nfrom pip._in"
  },
  {
    "path": "tests/test_sync.py",
    "chars": 16250,
    "preview": "from __future__ import annotations\n\nimport io\nimport os\nimport sys\nimport tempfile\nfrom collections import Counter\nfrom "
  },
  {
    "path": "tests/test_top_level_editable.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "tests/test_utils.py",
    "chars": 28233,
    "preview": "from __future__ import annotations\n\nimport logging\nimport operator\nimport os\nimport shlex\nimport sys\nimport typing as _t"
  },
  {
    "path": "tests/test_writer.py",
    "chars": 13523,
    "preview": "from __future__ import annotations\n\nimport sys\n\nimport pytest\nfrom pip._internal.models.format_control import FormatCont"
  },
  {
    "path": "tests/unit/_internal/pip_api/test_cli_options.py",
    "chars": 769,
    "preview": "from __future__ import annotations\n\nimport pytest\nfrom pip._internal.commands import create_command\n\nfrom piptools._inte"
  },
  {
    "path": "tests/unit/_internal/pip_api/test_install_requirements.py",
    "chars": 1023,
    "preview": "from __future__ import annotations\n\nimport pytest\n\nfrom piptools._internal import _pip_api\n\n\n@pytest.mark.skipif(\n    _p"
  },
  {
    "path": "tests/unit/_internal/pip_api/test_package_finder.py",
    "chars": 769,
    "preview": "from __future__ import annotations\n\nimport pytest\n\nfrom piptools._internal import _pip_api\nfrom piptools.repositories im"
  },
  {
    "path": "tests/unit/_internal/pip_api/test_pip_version.py",
    "chars": 324,
    "preview": "from __future__ import annotations\n\nimport sys\n\nimport pip\nfrom pip._vendor.packaging.version import Version\n\nfrom pipto"
  },
  {
    "path": "tests/unit/_internal/test_subprocess.py",
    "chars": 295,
    "preview": "from __future__ import annotations\n\nimport sys\n\nfrom piptools._internal import _subprocess\n\n\ndef test_run_python_snippet"
  },
  {
    "path": "tests/utils.py",
    "chars": 212,
    "preview": "from __future__ import annotations\n\nimport os\n\n# NOTE: keep in sync with \"passenv\" in tox.ini\nCI_VARIABLES = {\"CI\", \"GIT"
  },
  {
    "path": "towncrier.toml",
    "chars": 2513,
    "preview": "[tool.towncrier]\n  package = \"piptools\"\n  filename = \"CHANGELOG.md\"\n  start_string = \"<!-- towncrier release notes start"
  },
  {
    "path": "tox.ini",
    "chars": 6935,
    "preview": "[tox]\nenvlist =\n    # NOTE: keep this in sync with the env list in .github/workflows/ci.yml.\n    py{39,310,311,312,313,3"
  }
]

// ... and 12 more files (download for full content)

About this extraction

This page contains the full source code of the jazzband/pip-tools GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 140 files (617.0 KB), approximately 160.6k tokens, and a symbol index with 612 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!