{"id":15580449,"url":"https://github.com/sbidoul/pip-deepfreeze","last_synced_at":"2025-10-12T21:14:54.248Z","repository":{"id":37941515,"uuid":"278479259","full_name":"sbidoul/pip-deepfreeze","owner":"sbidoul","description":"A simple pip freeze workflow for Python application developers","archived":false,"fork":false,"pushed_at":"2025-03-24T17:55:47.000Z","size":1186,"stargazers_count":39,"open_issues_count":9,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-02T08:12:36.539Z","etag":null,"topics":["lockfile","packaging","python","requirements","virtualenv"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sbidoul.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-09T21:57:08.000Z","updated_at":"2025-01-29T09:38:50.000Z","dependencies_parsed_at":"2023-09-26T04:03:31.214Z","dependency_job_id":"f15048cb-0a64-46f9-a080-4da4f138763c","html_url":"https://github.com/sbidoul/pip-deepfreeze","commit_stats":{"total_commits":448,"total_committers":3,"mean_commits":"149.33333333333334","dds":0.0379464285714286,"last_synced_commit":"b3f0d88396288e2ae9dc2e8e012b32fdd231483a"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbidoul%2Fpip-deepfreeze","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbidoul%2Fpip-deepfreeze/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbidoul%2Fpip-deepfreeze/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sbidoul%2Fpip-deepfreeze/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sbidoul","download_url":"https://codeload.github.com/sbidoul/pip-deepfreeze/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248018061,"owners_count":21034048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["lockfile","packaging","python","requirements","virtualenv"],"created_at":"2024-10-02T19:26:11.228Z","updated_at":"2025-10-12T21:14:54.237Z","avatar_url":"https://github.com/sbidoul.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pip-deepfreeze\n\n![image](https://raw.githubusercontent.com/sbidoul/pip-deepfreeze/master/docs/logo.png)\n\nA simple pip freeze workflow for Python application developers.\n\n[![PyPI](https://img.shields.io/pypi/v/pip-deepfreeze?label=pypi%20package)](https://pypi.org/project/pip-deepfreeze/)\n[![PyPI - License](https://img.shields.io/pypi/l/pip-deepfreeze)](https://github.com/sbidoul/pip-deepfreeze/blob/master/LICENSE.txt)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pip-deepfreeze)](https://pypi.org/project/pip-deepfreeze/)\n[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/sbidoul/pip-deepfreeze/ci.yml?label=CI)](https://github.com/sbidoul/pip-deepfreeze/actions)\n\nTable of contents\n\n- [About](#about)\n- [Intallation](#installation)\n- [Quick Start](#quick-start)\n- [How to](#how-to)\n- [FAQ](#faq)\n- [CLI Reference](#cli-reference)\n- [Other tools](#other-tools)\n- [Development](#development)\n- [Contributing](#contributing)\n\n## About\n\n`pip-deepfreeze` aims at doing one thing and doing it well, namely\nmanaging the dependencies of a Python *application* in a virtual\nenvironment.\n\nThis includes:\n\n- installing the project in editable mode, and its dependencies,\n- updating the environment with new dependencies as the project evolves,\n- uninstalling unused dependencies,\n- refreshing dependencies,\n- maintaining pinned dependencies in `requirements.txt` lock files,\n- maintaining pinned optional dependencies in `requirements-{extra}.txt` lock files,\n- displaying installed dependencies as a tree.\n\nA few characteristics of this project:\n\n- It is easy to use, with a single `pip-df sync` command.\n- It is fast, with very little overhead on top of a regular\n  `pip install` + `pip freeze`.\n- It relies on the documented `pip` command line interface and its\n  ubiquitous [requirements file\n  format](https://pip.pypa.io/en/stable/user_guide/?highlight=requirements#requirements-files).\n- It assumes your project is configured using a PEP 517/660 compliant\n  build backend but otherwise makes no assumption on the specific\n  backend used.\n- It has first class support for dependencies specified as VCS\n  references.\n- It is written in Python 3.8+, yet works in any virtual environment\n  that has `pip` installed, including python 2 and python 3.6 and 3.7.\n- It works with pip-less virtual environments created with\n  `python3 -m venv --without-pip`.\n- It is reasonably small and simple, with good test coverage and is\n  hopefully easy to maintain.\n\n## Installation\n\nUsing [pipx](https://pypi.org/project/pipx/) (recommended):\n\n``` console\npipx install pip-deepfreeze\n```\n\nUsing [pip](https://pypi.org/project/pip/):\n\n``` console\npip install --user pip-deepfreeze\n```\n\n\u003e [!IMPORTANT]\n\u003e It is *not* recommended to install `pip-deepfreeze` in the same\n\u003e environment as your application, so its dependencies do not interfere\n\u003e with your app. By default it works with the `py` or `python`\n\u003e executable found in your `PATH` (which does what you normally expect\n\u003e in an activated virtualenv), but you can ask it to work within another\n\u003e environment using the `--python` option.\n\n## Quick start\n\n![pip-deepfreeze synopsis](https://raw.githubusercontent.com/sbidoul/pip-deepfreeze/41e960aecd1b142bad648d438143f55b6f50bba5/docs/synopsis.png)\n\nMake sure your application declares its direct dependencies in\n[pyproject.toml](https://packaging.python.org/en/latest/specifications/declaring-project-metadata/),\nor any other mechanism supported by your PEP 517/660 compliant build\nbackend.\n\nCreate and activate a virtual environment using your favorite tool.\n\n\u003e [!TIP]\n\u003e When you install `pip-deepfreeze`, it also installs `pip` so you don't\n\u003e need to install `pip` separately in your virtual environment (for\n\u003e instance, you may use `python3 -m venv --without-pip` to create it).\n\u003e However, if your virtual environment uses a Python version that is not\n\u003e supported by `pip-deepfreeze`'s bundled copy of `pip`, you will need\n\u003e to install `pip` in the target virtual environment.\n\n\u003e [!IMPORTANT]\n\u003e When using `pip` older than 23.1, you may need to also install\n\u003e `setuptools` and `wheel` in the virtual environment for best results.\n\nTo install your project in editable mode in the active virtual\nenvironment, go to your project root directory and run:\n\n``` console\npip-df sync\n```\n\nIf you don't have one yet, this will generate a file named\n`requirements.txt`, containing the exact version of all your application\ndependencies, as they were installed.\n\nYou can then add this `requirement.txt` to version control, and other\npeople collaborating on the project can install the project and its\nknown good dependencies using `pip-df sync` (or\n`pip install -r requirements.txt -e .` in a fresh virtualenv).\n\n\u003e [!TIP]\n\u003e `pip-deepfreeze` has experimental support for the [uv\n\u003e pip](https://github.com/astral-sh/uv) installer. To use it, run\n\u003e `pip-df sync --installer=uvpip`.\n\nWhen you add or remove dependencies of your project, run `pip-df sync`\nagain to update your environment and `requirements.txt`.\n\nTo update one or more dependencies to the latest allowed version, run:\n\n``` console\npip-df sync --update DEPENDENCY1,DEPENDENCY2 ...\n```\n\nIf you need to add some dependencies from VCS references (e.g. when a\nlibrary with a patch you need is not available as a release on a package\nindex), add the dependency as usual in your project, then add the VCS\nreference to a file named `constraints.txt` like this:\n\n    DEPENDENCYNAME @ git+https://g.c/org/project@branch\n\nThen run `pip-df sync`. It will update `requirements.txt` with a VCS\nreference pinned at the exact commit that was installed (you need pip\nversion 20.1 or greater for this to work). If later you need to update\nto the HEAD of the same branch, simply use\n`pip-df sync --update DEPENDENCYNAME`.\n\nWhen, later again, your branch is merged upstream and the project has\npublished a release, remove the line from `constraints.txt` and run\n`pip-df sync --update DEPENDENCYNAME` to update to the latest released\nversion.\n\n## How to\n\nCreating a new project.\n\n\u003e Follow the instructions of your favorite PEP 517/660 compliant build\n\u003e tool, such as `hatch`, `setuptools`, `flit` or others. After declaring\n\u003e the first dependencies, create and activate a virtualenv, then run\n\u003e `pip-df sync` in the project directory to generate pinned dependencies\n\u003e in `requirements.txt`.\n\nInstalling an existing project.\n\n\u003e After checking out the project from source control, create and\n\u003e activate activate virtualenv, the run `pip-df sync` to install the\n\u003e project.\n\nUpdating to the latest version of a project.\n\n\u003e After dependencies have been added to the project by others, update\n\u003e the source code from VCS, then run `pip-df sync` while in your\n\u003e activated virtualenv to bring it to the desired state: dependencies\n\u003e will be updated, removed or uninstalled as needed.\n\nAdding or removing dependencies.\n\n\u003e After you have added or removed dependencies to your build tool\n\u003e configuration, simply run `pip-df sync` to update your virtualenv. You\n\u003e will be prompted to uninstall unneeded dependencies.\n\nRefreshing some pinned dependencies.\n\n\u003e After a while you may want to refresh some or all of your dependencies\n\u003e to an up-to-date version. You can do so with\n\u003e `pip-df sync --update dep1,dep2,...`.\n\nRefreshing all pinned dependencies.\n\n\u003e To update all dependencies to the latest allowed version, you can use\n\u003e `pip-df sync --update-all`. This is equivalent to removing\n\u003e `requirements.txt` then running `pip-df sync`. This is also roughly\n\u003e equivalent to reinstalling in an empty virtualenv with\n\u003e `pip install -e . -c constraints.txt` then running\n\u003e `pip freeze \u003e requirements.txt`.\n\nUsing another package index than PyPI.\n\n\u003e Create a file named `constraints.txt` in your project root, and add\n\u003e pip options to it, such as `--index-url` or `--find-links`. You\n\u003e can add any option that [pip supports in requirements\n\u003e files](https://pip.pypa.io/en/stable/reference/pip_install/#requirements-file-format).\n\nInstalling dependencies from VCS.\n\n\u003e When one of your direct or indirect dependencies has a bug or a\n\u003e missing feature, it is convenient to do an upstream pull request then\n\u003e install from it. Assume for instance your project depends on the\n\u003e `packaging` library and you want to install a pull request you made to\n\u003e it. To do so, make sure `packaging` is declared as a regular\n\u003e dependency of your project. Then add the VCS reference in\n\u003e `constraints.txt` like so:\n\u003e\n\u003e     packaging @ git+https://github.com/you/packaging@your-branch\n\u003e\n\u003e Then run `pip-df sync --update packaging` to install from the branch\n\u003e and pin the exact commit in `requirements.txt` for reproducibility.\n\u003e When upstream merges your PR and cuts a release, you can simply remove\n\u003e the line from `constraints.txt` and run\n\u003e `pip-df sync --update packaging` to refresh to the latest released\n\u003e version.\n\nWorking with extras.\n\n\u003e Assuming your project configuration declares extra dependencies such\n\u003e as `tests` or `docs`, you can run `pip-df sync --extras tests,docs` to\n\u003e update your virtualenv with the necessary dependencies. This will also\n\u003e pin extra dependencies in `requirements-tests.txt` and\n\u003e `requirements-docs.txt`. Note that pip-deepfreeze assumes that the\n\u003e `extras` mechanism is used to specify *additional* dependencies to the\n\u003e base dependencies of the project.\n\n## FAQ\n\nWhat should I put in `constraints.txt`? Should I add all my dependencies\nthere?\n\n\u003e `constraints.txt` is optional. The dependencies of your project must\n\u003e be declared primarily in `pyproject.toml` (or the legacy\n\u003e `setup.py/setup.cfg`). `constraints.txt` may contain additional\n\u003e constraints if needed, such as version constraints on indirect\n\u003e dependencies that you don't control, or VCS links for dependencies\n\u003e that you need to install from VCS source.\n\nI have added a constraint in `constraints.txt` but `pip-df sync` does\nnot honor it. What is going on?\n\n\u003e `pip-df sync` always gives priority to versions pinned in\n\u003e `requirements.txt`, unless explicitly asked to do otherwise. After\n\u003e adding or changing constraints or VCS references for already pinned\n\u003e requirements, use the `--update` option like so:\n\u003e\n\u003e     pip-df sync --update DEPENDENCY1,DEPENDENCY2,...\n\n`pip-deepfreez` erroneously complains\npython is not running in a virtualenv.\n\n\u003e The most probable cause is that you used an older version of\n\u003e `virtualenv` which does not generate PEP 405 compliant virtual\n\u003e environments. `virtualenv` version 20 and later are supported, as well\n\u003e as the Python 3 native `venv` module. Should this problem be prevalent\n\u003e in practice, we may add support for older `virtualenv` versions, or\n\u003e add an option to ignore the virtualenv sanity check (which is only\n\u003e there to prevent `pip-deepfreeze` to corrupt the system Python\n\u003e packages by accident).\n\nHow can I pass options to pip?\n\n\u003e The most reliable and repeatable way to pass options to pip is to add\n\u003e them in `constraints.txt`. The pip documentation lists [options that\n\u003e are allowed in requirements\n\u003e files](https://pip.pypa.io/en/stable/reference/pip_install/#requirements-file-format).\n\u003e Global options can also be set in the pip configuration file or passed\n\u003e via `PIP_*` environment variables (see the pip documentation for more\n\u003e information).\n\nWhy not using `pip install` and `pip freeze` manually?\n\n\u003e `pip-df sync` combines both commands in one and ensures your\n\u003e environment and pinned requirements remain correct and up-to-date.\n\u003e Some error prone operations it facilitates include: uninstalling\n\u003e unneeded dependencies, updating selected dependencies, overriding\n\u003e dependencies with VCS references, etc.\n\nIs there a recommended way to deploy my project in the production\nenvironment?\n\n\u003e There are many possibilities. One approach that works well (and is\n\u003e recommended in the pip documentation) works with two simple steps.\n\u003e First you build the wheel files for your project and dependencies,\n\u003e using:\n\u003e\n\u003e     pip wheel --no-deps -r requirements.txt -e . --wheel-dir=./wheel-dir\n\u003e\n\u003e Then you ship the content of the `wheel-dir` directory to your target\n\u003e environment or docker image, and run:\n\u003e\n\u003e     pip install --no-index --find-links=./wheel-dir project-name\n\u003e\n\u003e Note the use of `--no-deps` when building and `--no-index` when\n\u003e installing. This will ensure that all the required dependencies are\n\u003e effectively pinned in `requirements.txt`.\n\n## CLI reference\n\n\u003e [!NOTE]\n\u003e The command line interface is the only supported public interface. If\n\u003e you find yourself writing `import pip_deepfreeze`, please don't, as\n\u003e everything may change without notice. Or rather, get in touch to\n\u003e discuss your needs.\n\n### Global options\n\n```\nUsage: pip-df [OPTIONS] COMMAND [ARGS]...\n\n  A simple pip freeze workflow for Python application developers.\n\nOptions:\n  -p, --python, --py PYTHON     The python executable to use. Determines the\n                                python environment to work on. Defaults to the\n                                'py' or 'python' executable found in PATH.\n  -r, --project-root DIRECTORY  The project root directory.  [default: .]\n  --min-version VERSION         Minimum version of pip-deepfreeze required.\n  --version                     Show the version and exit.\n  -v, --verbose\n  --install-completion          Install completion for the current shell.\n  --show-completion             Show completion for the current shell, to copy\n                                it or customize the installation.\n  --help                        Show this message and exit.\n\nCommands:\n  sync  Install/update the environment to match the project requirements.\n  tree  Print the installed dependencies of the project as a tree.\n```\n\n### pip-df sync\n\n```\nUsage: pip-df sync [OPTIONS]\n\n  Install/update the environment to match the project requirements.\n\n  Install/reinstall the project. Install/update dependencies to the latest\n  allowed version according to pinned dependencies in requirements.txt or\n  constraints in constraints.txt/requirements.txt.in. On demand update of\n  dependencies to to the latest version that matches constraints. Optionally\n  uninstall unneeded dependencies.\n\nOptions:\n  -u, --update DEP1,DEP2,...      Make sure selected dependencies are upgraded\n                                  (or downgraded) to the latest allowed\n                                  version. If DEP is not part of your\n                                  application dependencies anymore, this\n                                  option has no effect.\n  --update-all                    Upgrade (or downgrade) all dependencies of\n                                  your application to the latest allowed\n                                  version.\n  -x, --extras EXTRA1,EXTRA2,...  Comma separated list of extras to install\n                                  and freeze to requirements-{EXTRA}.txt.\n  --uninstall-unneeded / --no-uninstall-unneeded\n                                  Uninstall distributions that are not\n                                  dependencies of the project. If not\n                                  specified, ask confirmation.\n  --pre-sync-command TEXT         Command to run before the sync operation.\n                                  Can be specified multiple times.\n  --post-sync-command TEXT        Command to run after the sync operation is\n                                  complete. Can be specified multiple times.\n  --installer [pip|uvpip]         [default: pip]\n  --build-contraints FILE\n  --help                          Show this message and exit.\n```\n\n### pip-df tree\n\n```\nUsage: pip-df tree [OPTIONS]\n\n  Print the installed dependencies of the project as a tree.\n\nOptions:\n  -x, --extras EXTRA1,EXTRA2,...  Extras of project to consider when looking\n                                  for dependencies.\n  --help                          Show this message and exit.```\n\n## Configuration\n\nMost options can get default values from a `[tool.pip-deepfreeze]`\nsection of your `pyproject.toml` file. For instance:\n\n- `sync.extras`: default value for the `--extras` option of the `sync`\n  command.\n- `sync.post_sync_commands`: default value (as a list of strings) for\n  the `--post-sync-command` options of the `sync` command.\n- `sync.installer`\n- `min_version`\n\nExample:\n\n``` toml\n[tool.pip-deepfreeze]\nmin_version = \"2.0\"\n\n[tool.pip-deepfreeze.sync]\nextras = \"test,doc\"\npost_sync_commands = [\"pip-preserve-requirements requirements*.txt\"]\ninstaller = \"uvpip\"\n```\n\n## Other tools\n\nSeveral other tools exist with a similar or overlapping scope as\n`pip-deepfreeze`.\n\n- [pip](https://pip.pypa.io/en/stable/) itself. `pip-deepfreeze` relies\n  extensively on the `pip` CLI for installation and querying the\n  database of installed distributions. In essence it is a thin wrapper\n  around `pip install` and `pip freeze`. Some of the features here may\n  serve as inspiration for future `pip` evolutions.\n- [pip-tools](https://pypi.org/project/pip-tools/). This is the one with\n  the most similar features. Besides the reasons explained in\n  [About](#about) above I wanted to see if it was possible to do such a\n  thing using the `pip` CLI only. `pip-deepfreeze` is also more\n  opinionated than `pip-tools` and `pipdeptree`, as it always does an\n  editable install and it uses the build backend to obtain the top level\n  dependencies.\n- [uv](https://pypi.org/project/uv/)\n- [PDM](https://pypi.org/project/pdm/)\n- [Poetry](https://python-poetry.org/)\n- [pipenv](https://pipenv.pypa.io/en/latest/)\n- [pipdeptree](https://pypi.org/project/pipdeptree/). Works similarly as\n  `pip-df tree`. It is convenient to have a tree command in pip-deepfreeze, that\n  shares the exact same notion of top level dependencies.\n\n## Development\n\nTo run tests, use `tox`. You will get a test coverage report in\n`htmlcov/index.html`. An easy way to install tox is `pipx install tox`.\n\nThis project uses [pre-commit](https://pre-commit.com/) to enforce\nlinting (among which [black](https://pypi.org/project/black/) for code\nformating, [isort](https://pypi.org/project/isort/) for sorting imports,\nand [mypy](https://pypi.org/project/mypy/) for type checking).\n\nTo make sure linters run locally on each of your commits, install\npre-commit (`pipx install pre-commit` is recommended), and run\n`pre-commit install` in your local clone of the `pip-deepfreeze`\nrepository.\n\nTo release:\n\n- Select the next version number of the form `X.Y(.Z)`.\n- `towncrier --version X.Y(.Z)`.\n- Inspect and commit the updated `CHANGELOG.md`.\n- On GitHub, create a new release. Choose a tag of the form `vX.Y(.Z)`. Click `Generate\n  release notes` and copy over the content from `CHANGELOG.md`.\n\n## Contributing\n\nWe welcome contributions of all kinds.\n\nPlease consult the [issue\ntracker](https://github.com/sbidoul/pip-deepfreeze/issues) to discover\nthe roadmap and known bugs.\n\nBefore opening a pull request, please create an issue first to discuss\nthe bug or feature request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsbidoul%2Fpip-deepfreeze","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsbidoul%2Fpip-deepfreeze","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsbidoul%2Fpip-deepfreeze/lists"}