Package: pip-deepfreeze
A simple pip freeze workflow for Python application developers.Table of contentsAboutInstallationQuick startHow toFAQCLI referenceGlobal optionspip-df syncpip-df treeConfigurationOther toolsDevelopmentContributingAboutpip-deepfreezeaims at doing one thing and doing it well, namely managing
the dependencies of a Pythonapplicationin a virtual environment.This includes:installing the project in editable mode, and its dependencies,updating the environment with new dependencies as the project evolves,uninstalling unused dependencies,refreshing dependencies,maintaining pinned inrequirements.txtlock files,pinning versions for extras inrequirements-{extra}.txtlock files,displaying installed dependencies as a tree.A few characteristics of this project:It is easy to use, with a singlepip-dfsynccommand.It is fast, with very little overhead on top of a regularpip install+pip freeze.It relies on the documentedpipcommand line interface and its
ubiquitousrequirements file
format.It assumes your project is configured using a PEP 517/660 compliant build
backend but otherwise makes no assumption on the specific backend
used.It has first class support for dependencies specified as VCS references.It is written in Python 3.8+, yet works in any virtual environment
that haspipinstalled, including python 2 and python 3.6 and 3.7.It works with pip-less virtual environments created withpython3-mvenv--without-pip.It is reasonably small and simple, with good test coverage and is hopefully
easy to maintain.InstallationUsingpipx(recommended):pipx install pip-deepfreezeUsingpip:pip install --user pip-deepfreezeNoteIt isnotrecommended to installpip-deepfreezein the same environment as your
application, so its dependencies do not interfere with your app. By default it works
with thepyorpythonexecutable found in yourPATH(which does what you
normally expect in an activated virtualenv), but you can ask it to work within
another environment using the--pythonoption.Quick startMake sure your application declares its direct dependencies inpyproject.toml,
or any other mechanism supported by your PEP 517/660 compliant build backend.Create and activate a virtual environment using your favorite tool. Runpip listto make surepip,setuptoolsandwheelare installed
in the virtualenv.To install your project in editable mode in the active virtual
environment, go to your project root directory and run:pip-df syncIf you don’t have one yet, this will generate a file namedrequirements.txt,
containing the exact version of all your application dependencies, as they were
installed.You can then add thisrequirement.txtto version control, and other people
collaborating on the project can install the project and its known good
dependencies usingpip-dfsync(orpip install-rrequirements.txt-e.in a fresh virtualenv).Notepip-deepfreezehas experimental support for theuvinstaller. To use it, runpip-dfsync--installer=uv.When you add or remove dependencies of your project, runpip-dfsyncagain
to update your environment andrequirements.txt.To update one or more dependencies to the latest allowed version, run:pip-df sync --update DEPENDENCY1,DEPENDENCY2 ...If you need to add some dependencies from VCS references (e.g. when a library
with a patch you need is not available as a release on a package index), add
the dependency as usual in your project, then add the VCS reference to a file
namedconstraints.txtlike this:DEPENDENCYNAME @ git+https://g.c/org/project@branchThen runpip-dfsync. It will updaterequirements.txtwith a VCS
reference pinned at the exact commit that was installed (you need pip version
20.1 or greater for this to work). If later you need to update to the HEAD of
the same branch, simply usepip-dfsync--updateDEPENDENCYNAME.When, later again, your branch is merged upstream and the project has published
a release, remove the line fromconstraints.txtand runpip-dfsync--updateDEPENDENCYNAMEto update to the latest released version.How toCreating a new project.Follow the instructions of your favorite PEP 517/660 compliant build tool, such
ashatch,setuptools,flitor others. After declaring the first
dependencies, create and activate a virtualenv, then runpip-dfsyncin
the project directory to generate pinned dependencies inrequirements.txt.Installing an existing project.After checking out the project from source control, create and activate
activate virtualenv, the runpip-dfsyncto install the project.Updating to the latest version of a project.After dependencies have been added to the project by others, update the
source code from VCS, then runpip-dfsyncwhile in your activated
virtualenv to bring it to the desired state: dependencies will be updated,
removed or uninstalled as needed.Adding or removing dependencies.After you have added or removed dependencies to your build tool
configuration, simply runpip-dfsyncto update your virtualenv.
You will be prompted to uninstall unneeded dependencies.Refreshing some pinned dependencies.After a while you may want to refresh some or all of your dependencies to an
up-to-date version. You can do so withpip-dfsync--updatedep1,dep2,....Refreshing all pinned dependencies.To update all dependencies to the latest allowed version, you can usepip-dfsync--update-all. This is equivalent to removingrequirements.txtthen runningpip-dfsync. This is also roughly
equivalent to reinstalling in an empty virtualenv withpip install-e.-cconstraints.txtthen runningpip freeze > requirements.txt.Using another package index than PyPI.Create a file namedconstraints.txtin your project root, and add
pip options to it, such as--extra-index-urlor--find-links. You
can add any option thatpip supports in requirements files.Installing dependencies from VCS.When one of your direct or indirect dependencies has a bug or a missing
feature, it is convenient to do an upstream pull request then install from
it. Assume for instance your project depends on thepackaginglibrary
and you want to install a pull request you made to it. To do so, make surepackagingis declared as a regular dependency of your project. Then
add the VCS reference inconstraints.txtlike so:packaging @ git+https://github.com/you/packaging@your-branchThen runpip-dfsync--updatepackagingto install from the branch and
pin the exact commit inrequirements.txtfor reproducibility. When
upstream merges your PR and cuts a release, you can simply remove the line
fromconstraints.txtand runpip-dfsync--updatepackagingto
refresh to the latest released version.Working with extras.Assuming your project configuration declares extra dependencies such astestsordocs, you can runpip-dfsync--extrastests,docsto
update your virtualenv with the necessary dependencies. This will also pin
extra dependencies inrequirements-tests.txtandrequirements-docs.txt. Note that pip-deepfreeze assumes that theextrasmechanism is used to specifyadditionaldependencies to the
base dependencies of the project.FAQWhat should I put inconstraints.txt? Should I add all my dependencies
there?constraints.txtis optional. The dependencies of your project must be
declared primarily inpyproject.toml(or the legacysetup.py/setup.cfg).constraints.txtmay contain additional constraints if needed, such as version
constraints on indirect dependencies that you don’t control, or VCS links for
dependencies that you need to install from VCS source.I have added a constraint inconstraints.txtbutpip-dfsyncdoes
not honor it. What is going on?pip-dfsyncalways gives priority to versions pinned inrequirements.txt,
unless explicitly asked to do otherwise. After adding or changing constraints or VCS
references for already pinned requirements, use the--updateoption like so:pip-df sync --update DEPENDENCY1,DEPENDENCY2,...pip-deepfreezeerroneously complains python is not running in a virtualenv.The most probable cause is that you used an older version ofvirtualenvwhich does not generate PEP 405 compliant virtual environments.virtualenvversion 20 and later are supported, as well as the Python 3
nativevenvmodule. Should this problem be prevalent in practice, we may
add support for oldervirtualenvversions, or add an option to ignore
the virtualenv sanity check (which is only there to preventpip-deepfreezeto corrupt the system Python packages by accident).How can I pass options to pip?The most reliable and repeatable way to pass options to pip is to add them
inconstraints.txt. The pip documentation listsoptions that are
allowed in requirements files.
Global options can also be set in the pip configuration file or passed viaPIP_*environment variables (see the pip documentation for more
information).Why not usingpip installandpip freezemanually?pip-dfsynccombines both commands in one and ensures your environment
and pinned requirements remain correct and up-to-date. Some error prone
operations it facilitates include: uninstalling unneeded dependencies,
updating selected dependencies, overriding dependencies with VCS references,
etc.Is there a recommended way to deploy my project in the production environment?There are many possibilities. One approach that works well (and is
recommended in the pip documentation) works with two simple steps. First you
build the wheel files for your project and dependencies, using:pip wheel --no-deps -r requirements.txt -e . --wheel-dir=./wheel-dirThen you ship the content of thewheel-dirdirectory to your target
environment or docker image, and run:pip install --no-index --find-links=./wheel-dir project-nameNote the use of--no-depswhen building and--no-indexwhen
installing. This will ensure that all the required dependencies are
effectively pinned inrequirements.txt.CLI referenceNoteThe command line interface is the only supported public interface. If you
find yourself writingimport pip_deepfreeze, please don’t, as everything
may change without notice. Or rather, get in touch to discuss your needs.Global optionsUsage: pip-df [OPTIONS] COMMAND [ARGS]...

A simple pip freeze workflow for Python application developers.

Options:
  -p, --python, --py PYTHON     The python executable to use. Determines the
                                python environment to work on. Defaults to the
                                'py' or 'python' executable found in PATH.
  -r, --project-root DIRECTORY  The project root directory.  [default: .]
  --min-version      VERSION    Minimum version of pip-deepfreeze required.
  --version                     Show the version and exit.
  -v, --verbose
  --install-completion          Install completion for the current shell.
  --show-completion             Show completion for the current shell, to copy
                                it or customize the installation.
  --help                        Show this message and exit.

Commands:
  sync  Install/update the environment to match the project requirements.
  tree  Print the installed dependencies of the project as a tree.pip-df syncUsage: pip-df sync [OPTIONS]

  Install/update the environment to match the project requirements, and lock new
  dependencies.

  Install/reinstall the project. Install/update dependencies to the latest
  allowed version according to pinned dependencies in requirements.txt or
  constraints in constraints.txt. On demand update of dependencies to to
  the latest version that matches constraints. Optionally uninstall unneeded
  dependencies.

Options:
  -u, --update DEP1,DEP2,...      Make sure selected dependencies are upgraded
                                  (or downgraded) to the latest allowed
                                  version. If DEP is not part of your
                                  application dependencies anymore, this
                                  option has no effect.

  --update-all                    Upgrade (or downgrade) all dependencies of
                                  your application to the latest allowed
                                  version.

  -x, --extras EXTRA1,EXTRA2,... Comma separated list of extras to install
                                  and freeze to requirements-{EXTRA}.txt.

  --post-sync-command TEXT        Command to run after the sync operation is
                                  complete. Can be specified multiple times.

  --uninstall-unneeded / --no-uninstall-unneeded
                                  Uninstall distributions that are not
                                  dependencies of the project. If not
                                  specified, ask confirmation.

  --installer [pip|uv]

  --help                          Show this message and exit.pip-df treeUsage: pip-df tree [OPTIONS]

  Print the installed dependencies of the project as a tree.

Options:
  -x, --extras EXTRA1,EXTRA2,...  Extras of project to consider when looking for
                                  dependencies.

  --help                          Show this message and exit.ConfigurationMost options can get default values from a[tool.pip-deepfreeze]section of yourpyproject.tomlfile. For instance:sync.extras: default value for the--extrasoption of thesynccommand.sync.post_sync_commands: default value (as a list of strings) for the--post-sync-commandoptions of thesynccommand.sync.installermin_versionExample:[tool.pip-deepfreeze]min_version="2.0"[tool.pip-deepfreeze.sync]extras="test,doc"post_sync_commands=["pip-preserve-requirements requirements*.txt"]installer="uv"Other toolsSeveral other tools exist with a similar or overlapping scope aspip-deepfreeze.pipitself.pip-deepfreezerelies
extensively on thepipCLI for installation and querying the database of
installed distributions. In essence it is a thin wrapper aroundpip installandpip freeze. Some of the features here may serve as
inspiration for futurepipevolutions.pip-tools. This is the one with the most
similar features. Besides the reasons explained inAboutabove I wanted to see if
it was possible to do such a thing using thepipCLI only.pip-deepfreezeis
also more opinionated thanpip-toolsandpipdeptree,  as it always does an
editable install and it uses the build backend to obtain the top level dependencies.PDMPoetrypipenvpipdeptree. Works similarly aspip-df tree.DevelopmentTo run tests, usetox. You will get a test coverage report inhtmlcov/index.html. An easy way to install tox ispipx install tox.This project usespre-committo enforce linting
(among whichblackfor code formating,isortfor sorting imports, andmypyfor type checking).To make sure linters run locally on each of your commits, install pre-commit
(pipx installpre-commitis recommended), and runpre-commitinstallin
your local clone of thepip-deepfreezerepository.To release:Select the next version number of the formX.Y.Z.towncrier--versionvX.Y.Z.Inspect and commit the updatedHISTORY.rst.git tag vX.Y.Z ; git push--tags.ContributingWe welcome contributions of all kinds.Please consult theissue trackerto discover the roadmap
and known bugs.Before opening a pull request, please create an issue first to discuss the bug or
feature request.