···641- [pypi2nix](https://github.com/garbas/pypi2nix) by Rok Garbas
642- [pypi2nix](https://github.com/offlinehacker/pypi2nix) by Jaka Hudoklin
6430000000000000644## FAQ
645646### How can I install a working Python environment?
···641- [pypi2nix](https://github.com/garbas/pypi2nix) by Rok Garbas
642- [pypi2nix](https://github.com/offlinehacker/pypi2nix) by Jaka Hudoklin
643644+### Deterministic builds
645+646+Python 2.7, 3.5 and 3.6 are now built deterministically and 3.4 mostly.
647+Minor modifications had to be made to the interpreters in order to generate
648+deterministic bytecode. This has security implications and is relevant for
649+those using Python in a `nix-shell`.
650+651+When the environment variable `DETERMINISTIC_BUILD` is set, all bytecode will have timestamp 1.
652+The `buildPythonPackage` function sets `DETERMINISTIC_BUILD` as well as
653+[PYTHONHASHSEED](https://docs.python.org/3.5/using/cmdline.html#envvar-PYTHONHASHSEED).
654+Both are also exported in `nix-shell`.
655+656+657## FAQ
658659### How can I install a working Python environment?
···271 </para>
272 </listitem>
273274+ <listitem>
275+ <para>
276+ Python 2.7, 3.5 and 3.6 are now built deterministically and 3.4 mostly.
277+ Minor modifications had to be made to the interpreters in order to generate
278+ deterministic bytecode. This has security implications and is relevant for
279+ those using Python in a <literal>nix-shell</literal>. See the Nixpkgs manual
280+ for details.
281+ </para>
282+ </listitem>
283+284</itemizedlist>
285286
···3compressManPages() {
4 local dir="$1"
56- if [ ! -d "$dir/share/man" ]; then return; fi
7- echo "gzipping man pages in $dir"
0089- GLOBIGNORE=.:..:*.gz:*.bz2
10-11- for f in "$dir"/share/man/*/* "$dir"/share/man/*/*/*; do
12- if [ -f "$f" -a ! -L "$f" ]; then
13- if gzip -c -n "$f" > "$f".gz; then
14- rm "$f"
15- else
16- rm "$f".gz
17- fi
18 fi
19 done
2021- for f in "$dir"/share/man/*/* "$dir"/share/man/*/*/*; do
22- if [ -L "$f" -a -f `readlink -f "$f"`.gz ]; then
23- ln -sf `readlink "$f"`.gz "$f".gz && rm "$f"
0000024 fi
25 done
26-27- unset GLOBIGNORE
28}
···3compressManPages() {
4 local dir="$1"
56+ if [ -L "$dir"/share ] || [ -L "$dir"/share/man ] || [ ! -d "$dir/share/man" ]
7+ then return
8+ fi
9+ echo "gzipping man pages under $dir/share/man/"
1011+ # Compress all uncompressed manpages. Don't follow symlinks, etc.
12+ find "$dir"/share/man/ -type f -a '!' -regex '.*\.\(bz2\|gz\)$' -print0 \
13+ | while IFS= read -r -d $'\0' f
14+ do
15+ if gzip -c -n "$f" > "$f".gz; then
16+ rm "$f"
17+ else
18+ rm "$f".gz
019 fi
20 done
2122+ # Point symlinks to compressed manpages.
23+ find "$dir"/share/man/ -type l -a '!' -regex '.*\.\(bz2\|gz\)$' -print0 \
24+ | while IFS= read -r -d $'\0' f
25+ do
26+ local target
27+ target="$(readlink -f "$f")"
28+ if [ -f "$target".gz ]; then
29+ ln -sf "$target".gz "$f".gz && rm "$f"
30 fi
31 done
0032}
···5758 inherit pythonPath;
5960- # patch python interpreter to write null timestamps when compiling python files
61- # this way python doesn't try to update them when we freeze timestamps in nix store
062 DETERMINISTIC_BUILD=1;
006364 buildInputs = [ wrapPython ] ++ buildInputs ++ pythonPath
65 ++ [ (ensureNewerSourcesHook { year = "1980"; }) ]
···5758 inherit pythonPath;
5960+61+ # Determinism: The interpreter is patched to write null timestamps when compiling python files.
62+ # This way python doesn't try to update them when we freeze timestamps in nix store.
63 DETERMINISTIC_BUILD=1;
64+ # Determinism: We fix the hashes of str, bytes and datetime objects.
65+ PYTHONHASHSEED = 0;
6667 buildInputs = [ wrapPython ] ++ buildInputs ++ pythonPath
68 ++ [ (ensureNewerSourcesHook { year = "1980"; }) ]
···1516 patches = [ ./ploticus-install.patch ];
1700000018 meta = with stdenv.lib; {
19 description = "A non-interactive software package for producing plots and charts";
20 longDescription = ''Ploticus is a free, GPL'd, non-interactive
···1516 patches = [ ./ploticus-install.patch ];
1718+ # Make the symlink relative instead of absolute.
19+ # Otherwise it breaks when auto-moved to $out/share.
20+ preFixup = ''
21+ ln -sf pl.1 "$out"/man/man1/ploticus.1
22+ '';
23+24 meta = with stdenv.lib; {
25 description = "A non-interactive software package for producing plots and charts";
26 longDescription = ''Ploticus is a free, GPL'd, non-interactive