How to install data_files of python package into home directory

1.9k views Asked by At

Here's my setup.py

setup(
    name='shipane_sdk',

    version='1.0.0.a5',

    # ...

    data_files=[(os.path.join(os.path.expanduser('~'), '.shipane_sdk', 'config'), ['config/scheduler-example.ini'])],

    # ...
)

Packing & Uploading commands:

python setup.py sdist
python setup.py bdist_wheel --universal
twine upload dist/*

Installing command:

pip install shipane_sdk

But, it doesn't install the config/scheduler-example.ini under ~/.shipane_sdk

The pip documents says:

setuptools allows absolute “data_files” paths, and pip honors them as absolute, when installing from sdist. This is not true when installing from wheel distributions. Wheels don’t support absolute paths, and they end up being installed relative to “site-packages”. For discussion see wheel Issue #92.

Do you know how to do installing from sdist?

1

There are 1 answers

1
Julia Niewiejska On

There are multiple solutions to this problem and it is all very confusing how inconsistent the packaging tools work. Some time ago I found the following workaround worked for me best with sdist (note that it doesn't work with wheels!):

  1. Instead of using data_files, attach the files to your package using MANIFEST.in, which in your case could look like this:

    include config/scheduler-example.ini
    
  2. Copy the files "manually" to chosen location using this snippet in setup.py:

    if 'install' in sys.argv:
        from pkg_resources import Requirement, resource_filename
        import os
        import shutil
    
        # retrieve the temporary path where the package has been extracted to for installation
        conf_path_temp = resource_filename(Requirement.parse(APP_NAME), "conf")
    
        # if the config directory tree doesn't exist, create it
        if not os.path.exists(CONFIG_PATH):
            os.makedirs(CONFIG_PATH)
    
        # copy every file from given location to the specified ``CONFIG_PATH``
        for file_name in os.listdir(conf_path_temp):
            file_path_full = os.path.join(conf_path_temp, file_name)
            if os.path.isfile(file_path_full):
                shutil.copy(file_path_full, CONFIG_PATH)
    

In my case "conf" was the subdirectory in the package that contained my data files and they were supposed to be installed into CONFIG_PATH which was something like /etc/APP_NAME