1

I am trying to create an RPM from my Python application on SLES12 SP2. This is my setup.py file:

import setuptools

setuptools.setup(name='MyApp',
                 version='1.2.3',
                 options={'bdist_rpm': {'post_install': 'post_install.sh',
                                        'post_uninstall': 'post_uninstall.sh'}})

Nothing special.

Running python setup.py bdist_rpm works. However, running python3 setup.py bdist_rpm does the following:

running bdist_rpm
running egg_info
writing top-level names to MyApp.egg-info/top_level.txt

...

byte-compiling /home/pedro/MyApp/build/bdist.linux-x86_64/rpm/BUILDROOT/MyApp-1.2.3-1.x86_64/usr/lib/python3.4/site-packages/MyApp/my_file.py to my_file.cpython-34.pyc

...

Processing files: MyApp-1.2.3-1.noarch
error: File not found: /home/pedro/MyApp/build/bdist.linux-x86_64/rpm/BUILDROOT/MyApp-1.2.3-1.x86_64/usr/lib/python3.4/site-packages/MyApp/my_file.py

RPM build errors:
    File not found: /home/pedro/MyApp/build/bdist.linux-x86_64/rpm/BUILDROOT/MyApp-1.2.3-1.x86_64/usr/lib/python3.4/site-packages/MyApp/my_file.py
error: command 'rpmbuild' failed with exit status 1

The problem appears to be that setuptools is generating a file that ends in .cpython-34.pyc, and later looks for a file without the .cpython-34 but can't find it.

The RPM generation process on Python 3 goes through distutils.util.byte_compile(), which in turn calls importlib.util.cache_from_source(path), where path is the file to be byte-compiled. cache_from_source() looks like this (abbreviated):

def cache_from_source(path, debug_override=None, *, optimization=None):
    path = _os.fspath(path)
    head, tail = _path_split(path)
    base, sep, rest = tail.rpartition('.')
    tag = sys.implementation.cache_tag
    if tag is None:
        raise NotImplementedError('sys.implementation.cache_tag is None')
    almost_filename = ''.join([(base if base else rest), sep, tag])
    optimization = str(optimization)
    if optimization != '':
        almost_filename = '{}.{}{}'.format(almost_filename, _OPT, optimization)
    return _path_join(head, _PYCACHE, almost_filename + BYTECODE_SUFFIXES[0])

The value of sys.implementation.cache_tag is 'cpython-34'. This attribute of sys does not exist in Python 2. So it looks like setuptools injects this tag into the filename during byte compilation, but later forgets that it modified the filename and fails because it's looking for the original name.

How can I:

  1. Disable byte-compilation during the RPM generation,
  2. Disable the use of the cache tag in the byte-compilation, or
  3. Make setuptools (or rpmbuild; not sure which one is searching for the original filename) be consistent in the filename it searches for?

This question suggests disabling the byte-compilation altogether in the spec file, but I am looking for a way to generate the RPM with just the straight python3 setup.py bdist_rpm --maybe-some-other-parameters command.

Pedro
  • 375
  • 5
  • 11

0 Answers0