Workaround: add the following build override to a python part
override-build:
export SOURCE_DATE_EPOCH=0
snapcraftctl build
Description/analysis:
When building a project with multiple identical python dependencies I consistently get an error like this:
Failed to stage: Parts 'openstack-projects' and 'cluster' have the following files, but with different contents:
bin/activate
bin/activate.csh
bin/activate.fish
bin/python3
pyvenv.cfg
bin/python3
lib/python3.8/site-packages/Flask-1.1.2.dist-info/RECORD
lib/python3.8/site-packages/__pycache__/easy_install.cpython-38.pyc
lib/python3.8/site-packages/certifi/__pycache__/__init__.cpython-38.pyc
lib/python3.8/site-packages/certifi/__pycache__/__main__.cpython-38.pyc
# many other .pyc files ...
While snapcraft suggests that I use something like `organize`, `filesets` and `stage`, the issue is that the source files for those dependencies are identical - there is no reason for any manual work here.
Apparently, as of python 3.7, .pyc files include a timestamp and a size of the source by default (PycInvalidationMode.TIMESTAMP). There is a way to override this behavior by setting the SOURCE_DATE_EPOCH environment variable to switch py_compile to using PycInvalidationMode.CHECKED_HASH:
invalidation_mode should be a member of the PycInvalidationMode enum and controls how the generated bytecode cache is invalidated at runtime. The default is PycInvalidationMode.CHECKED_HASH ***if the SOURCE_DATE_EPOCH environment variable is set***, otherwise ***the default is PycInvalidationMode.TIMESTAMP***.
TL;DR: as of python 3.7, .pyc files by default include a timestamp and a size of the source file which results in a change of a hash every time a .pyc file is generated for a given source file. This results in staging conflicts for python parts. /docs.python. org/3/library/ py_compile. html#py_ compile. compile /docs.python. org/3/library/ py_compile. html#py_ compile. PycInvalidation Mode.TIMESTAMP
https:/
https:/
Workaround: add the following build override to a python part
override-build:
export SOURCE_DATE_EPOCH=0
snapcraftctl build
Description/ analysis:
When building a project with multiple identical python dependencies I consistently get an error like this:
Failed to stage: Parts 'openstack- projects' and 'cluster' have the following files, but with different contents: activate. csh activate. fish python3. 8/site- packages/ Flask-1. 1.2.dist- info/RECORD python3. 8/site- packages/ __pycache_ _/easy_ install. cpython- 38.pyc python3. 8/site- packages/ certifi/ __pycache_ _/__init_ _.cpython- 38.pyc python3. 8/site- packages/ certifi/ __pycache_ _/__main_ _.cpython- 38.pyc
bin/activate
bin/
bin/
bin/python3
pyvenv.cfg
bin/python3
lib/
lib/
lib/
lib/
# many other .pyc files ...
While snapcraft suggests that I use something like `organize`, `filesets` and `stage`, the issue is that the source files for those dependencies are identical - there is no reason for any manual work here.
Source hashes are the same:
snapcraft- microstack # sha256sum ./parts/ cluster/ install/ lib/python3. 8/site- packages/ click/_ textwrap. py b639bd7e843937d fcc39e69824c063 025b6e15aebd9f8 8976
6a30b3933165cb9
./parts/ cluster/ install/ lib/python3. 8/site- packages/ click/_ textwrap. py microstack # sha256sum ./parts/ openstack- projects/ install/ lib/python3. 8/site- packages/ click/_ textwrap. py b639bd7e843937d fcc39e69824c063 025b6e15aebd9f8 8976 ./parts/ openstack- projects/ install/ lib/python3. 8/site- packages/ click/_ textwrap. py
snapcraft-
6a30b3933165cb9
.pyc files are different:
snapcraft- microstack # sha256sum ./parts/ openstack- projects/ install/ lib/python3. 8/site- packages/ click/_ _pycache_ _/_textwrap. cpython- 38.pyc 9da73153e42d48d cd5d917bd637a0e 0af1eb6999f19fb 1085 ./parts/ openstack- projects/ install/ lib/python3. 8/site- packages/ click/_ _pycache_ _/_textwrap. cpython- 38.pyc
398b47a5abfc87e
snapcraft- microstack # sha256sum ./parts/ cluster/ install/ lib/python3. 8/site- packages/ click/_ _pycache_ _/_textwrap. cpython- 38.pyc 28944a1d31ff728 e7ef6529a7a8889 8f6568ea6e96d1f 8f82 ./parts/ cluster/ install/ lib/python3. 8/site- packages/ click/_ _pycache_ _/_textwrap. cpython- 38.pyc
d4642cfecd727d2
RECORD files include hashes as well, hence they are also different:
snapcraft- microstack # diff ./parts/ openstack- projects/ install/ lib/python3. 8/site- packages/ Flask-1. 1.2.dist- info/RECORD ./parts/ cluster/ install/ lib/python3. 8/site- packages/ Flask-1. 1.2.dist- info/RECORD ./bin/flask, sha256= VXQqccMeG03Rn8_ yN8Kq3Up13rzyao HsEckFnCxHor4, 242 ./bin/flask, sha256= NAzPpe84iZFX3PY sCZEirt3fAFObAj BuCpM25792kSU, 231
1c1
< ../../.
---
> ../../.
Apparently, as of python 3.7, .pyc files include a timestamp and a size of the source by default (PycInvalidatio nMode.TIMESTAMP ). There is a way to override this behavior by setting the SOURCE_DATE_EPOCH environment variable to switch py_compile to using PycInvalidation Mode.CHECKED_ HASH:
https:/ /docs.python. org/3/library/ py_compile. html compile( file, cfile=None, dfile=None, doraise=False, optimize=-1, invalidation_ mode=PycInvalid ationMode. TIMESTAMP, quiet=0)
py_compile.
invalidation_mode should be a member of the PycInvalidationMode enum and controls how the generated bytecode cache is invalidated at runtime. The default is PycInvalidation Mode.CHECKED_ HASH ***if the SOURCE_DATE_EPOCH environment variable is set***, otherwise ***the default is PycInvalidation Mode.TIMESTAMP* **.
https:/ /docs.python. org/3/library/ py_compile. html#py_ compile. PycInvalidation Mode.TIMESTAMP
TIMESTAMP
The .pyc file includes the timestamp and size of the source file, which Python will compare against the metadata of the source file at runtime to determine if the .pyc file needs to be regenerated.
https:/ /docs.python. org/3/library/ py_compile. html#py_ compile. PycInvalidation Mode.CHECKED_ HASH
CHECKED_HASH
The .pyc file includes a hash of the source file content, which Python will compare against the source at runtime to determine if the .pyc file needs to be regenerated.
The following workaround works because environment variables are passed down by default from the parent process in subprocess functions.
override-build:
export SOURCE_DATE_EPOCH=0
snapcraftctl build