Constraints files are requirements files that only control which version of a requirement is installed, not whether it is installed or not.

- Pip documentation

In a previous post, I talked about ditching pip freeze because it didn't work well with second-level dependencies (especially cross-platform). I found an even better workflow where I use a requirements.txt and a constraints.txt file together. Check out the code in this commit.

requirements
├── constraints.txt
└── requirements.txt

Just add a second flag to pip install.

python3 -m pip install -r requirements.txt -c constraints.txt

Inside requirements.txt are packages blogthedata directly uses. 

# requirements.txt
black
Brotli
chromedriver-autoinstaller
coverage
Django
...

Constraints.txt  includes everything in requirements.txt plus sub-dependencies

# constraints.txt
black==22.3.0
Brotli==1.0.9
cachetools==5.2.0
certifi==2022.6.15
cffi==1.15.1
...

When used together, we are instructing pip to install everything in requirements.txt with the constraint that if anything is installed that is listed in constraints.txt, use the pinned version.

Now I can be certain sub-dependencies won't break my app without requiring that the sub-dependencies be installed.