This is a project whose main goal is to test and demonstrate pypi2nix's capabilities and how to properly structure a project around it.
This project might also serve as a scafolding / template / example for new pypi2nix projects.
Some highlights of this project:
-
It uses by default a pinned nixpkgs set which you can find in
./nix/sandbox-pkgs.nix
. -
It uses a completely pure environment from which to run
pypi2nix
. This environment is defined in./nix/tools-deps.nix
which share the pinned<nixpkgs>
with the actual project environement. We use nix's shebang notation to run theupdate_from_requirements_txt.sh
. -
All
pypi2nix
arguments are encoded in theupdate_from_requirements_txt.sh
script which make runningpypi2nix
a reproducible process. -
Uses
setuptools_scm
to version the project so that a git tag such asv0.0.0
is used as the single source of truth for the project's version. -
Creation of encrypted distributions / releases using pyce. This is a tool which allow one to encrypt / sign all modules of a project and then, at runtime, hooking into the python import mechanic, unencrypt and validate the module. More info available at soroco blog post on pyce
-
Provide some helper script to help one through a private or unofficial (i.e: non pypi) release process using repositories. The project also demonstrate how to use such releases in a setuptools / pypi2nix compliant way.
Mandatory:
Optional:
-
This allows for automatically entering / reloading the nix environment.
Any other dependencies will be automatically introduced / managed by nix.
Note that this project has only been tested on linux but should work on any unix like system (i.e: systems supported by nix).
$ nix-shell
From this environment, you should have access to all python dependencies
specified in ./requirements-dev.txt
and ./requirements.txt
.
Using direnv, it is done automatically for you upon entering the project root dir or any of its sub dir. That is, unless this is the first time you do so:
$ cd jrg_pypi2nix_tests/
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
$ direnv allow
direnv: loading .envrc
direnv: using nix
# ...
$
[nix-shell] $ exit
[myuser@myuser] $ nix-shell
# ...
[nix-shell] $
Using direnv, it is much easier:
direnv reload
$ nix-build
or alternatively:
$ nix build
The result will be under ./result
.
Note that all the tests described in default.nix::checkPhase
will be
performed.
nix run -f .
From this environement, you should be able to use your program:
$ jrg_pypi2nix_tests
Note that same as described in building this project section above,
all test described in default.nix::checkPhase
will be performed.
$ ./nix/update_from_requirements_txt.sh
This utility script uses pypi2nix
in order to create a nix file with the set
of python dependencies specified by the following files:
requirements.txt
requirements-dev.txt
and generate the following files:
-
./nix/requirements_frozen.txt
The frozen requirements you are used to.
-
./nix/requirements.nix
A nix expression defining a python interpreter that has access to the frozen set of python dependencies.
-
A production dependency, then:
- Add it to
./requirements.txt
and./setup.cfg
.
- Add it to
-
A development or testing dependency, then:
- Add it to
./requirements-dev.txt
.
- Add it to
One would usually have done it this way:
$ python setup.py sdist
however, we created a helper script ./make_sdist
which will unpack the release
to a side repository ../jrg_pypi2nix_tests-sdist
allowing one to use mere
repository for the release process (e.g: for unofficial or private release).
This also allows one to more easily iterate through the validation process.
A similar ./make_bdist.sh
helper script is provided for producing a bdist
in the same fashion. However, it does not function as well with the nix store
(nix store paths are used).
Demonstrate the process of producing encrypted distributions / releases using pyce.
This is a tool which allow one to encrypt / sign all modules of a project and then, at runtime, hooking into the python import mechanic, unencrypt and validate the module.
More info available at soroco blog post on pyce
Same as above, we provide a simple to use helper script automating the whole process:
$ ./make_edist
# ...
Once completed, the following artefacts should have been produced:
-
../jrg_pypi2nix_tests
: A readily versionable folder similar to the sdist above but with a tweak: all*.py
module files will have been replaced by*.pyce
, an encrypted and signed version of the module. -
../jrg_pypi2nix_tests-edist.pyce_keys.json
: A json fragment containing one key per pyce encrypted / signed module. This should be kept secret and can later be used to decrypt the module files and validate their content.
Simply go to the edist directory making sure you enter the nix environement:
$ cd ../jrg_pypi2nix_tests-edist
$ nix-shell
# Launching the app with the keys.
$ ./launch_app_with_pyce_keys.sh
Hello world!
!
!
!
!
!
# lauching it wihout (to see it crash).
$ ./launch_app_without_pyce_keys.sh
Traceback (most recent call last):
File "/run/user/1000/tmp.ipl9fB3uVE/bin/jrg_pypi2nix_tests", line 11, in <module>
load_entry_point('jrg-pypi2nix-tests', 'console_scripts', 'jrg_pypi2nix_tests')()
File "/nix/store/di6ivk6qr43n948xjsr2ghsfc93dm18j-python3.7-bootstrapped-pip-19.0.3/lib/python3.7/site-packages/pkg_resources/__init__.py", line 489, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/nix/store/di6ivk6qr43n948xjsr2ghsfc93dm18j-python3.7-bootstrapped-pip-19.0.3/lib/python3.7/site-packages/pkg_resources/__init__.py", line 2793, in load_entry_point
return ep.load()
File "/nix/store/di6ivk6qr43n948xjsr2ghsfc93dm18j-python3.7-bootstrapped-pip-19.0.3/lib/python3.7/site-packages/pkg_resources/__init__.py", line 2411, in load
return self.resolve()
File "/nix/store/di6ivk6qr43n948xjsr2ghsfc93dm18j-python3.7-bootstrapped-pip-19.0.3/lib/python3.7/site-packages/pkg_resources/__init__.py", line 2417, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
File "../jrg_pypi2nix_tests-edist/src/jrg_pypi2nix_tests/main.py", line 2, in <module>
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 724, in exec_module
File "/nix/store/7ribnlk573ch5ad40ka3vcvhg604b4mf-python3.7-python3.7-pyce-1.0.0-patch1/lib/python3.7/site-packages/pyce/_imports.py", line 73, in get_code
data = decrypt(data, PYCEPathFinder.KEYS[normcase(relpath(path))])
KeyError: 'src/jrg_pypi2nix_tests/main_lib.pyce'
All of this code is released under the Apache v2.0 License.
See the copy at the root of this repository: LICENSE.