2

I have uploaded a package to PyPI that has file1 and file2 that users can edit for their specific configurations.

Now when I make changes to this package and the users decide to update their installation using pip install - U package, Is there a way for that file1 and file2 to be left as is, since if it does get upgraded users will have to redo their configs. Some code I can introduce in setup.py that can have the desired effect? Below is my setup.py

# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path

pwd = path.abspath(path.dirname(__file__))

with open(path.join(pwd, 'LICENSE.txt'), encoding='utf-8') as f:
    long_description = f.read()


setup(
    name='mypackage',

    # Using version number from git tag
    # use_scm_version={"root": "..", "relative_to": __file__},
    use_scm_version=True,
    setup_requires=['setuptools_scm'],

    description='XYZ',
    long_description=long_description,

    # The project's main homepage.
    url='https://www.google.com/',

    # Author details
    author='XYZ',
    author_email='xyz@xyz.com',

    # Choose your license
    license='See package description',

    # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
    classifiers=[
        # How mature is this project? Common values are
        #   3 - Alpha
        #   4 - Beta
        #   5 - Production/Stable
        'Development Status :: 3 - Alpha',

        # Keep updating supported frameworks here

        'Framework :: Django',

        # Indicate who your project is intended for
        'Intended Audience :: Developers',
        'Intended Audience :: System Administrators',
        'Intended Audience :: Information Technology',

        # Pick your license as you wish (should match "license" above)
        'License :: Other/Proprietary License',

        # Specify the Python versions you support here. In particular, ensure
        # that you indicate whether you support Python 2, Python 3 or both.
        'Programming Language :: Python :: 2.7',
    ],

    # Project associated keywords - space separated
    keywords='ca_apm_agent performance-monitoring development APM',

    # You can just specify the packages manually here if your project is
    # simple. Or you can use find_packages().
    packages=find_packages(exclude=['docs', 'tests']),

    # Alternatively, if you want to distribute just a my_module.py, uncomment
    # this:
    #   py_modules=["my_module"],

    # List run-time dependencies here.  These will be installed by pip when
    # your project is installed. For an analysis of "install_requires" vs pip's
    # requirements files see:
    # https://packaging.python.org/en/latest/requirements.html
    install_requires=[],

    # List additional groups of dependencies here (e.g. development
    # dependencies). You can install these using the following syntax,
    # for example:
    # $ pip install -e .[dev,test]
    extras_require={
        'dev': ['check-manifest'],
        'test': ['coverage'],
    },

    # If there are data files included in your packages that need to be
    # installed, specify them here.  If using Python 2.6 or less, then these
    # have to be included in MANIFEST.in as well.
    include_package_data=True,
    package_data={
        'mypackage': ['directives/file1, directives/file2'],
    },

    # Although 'package_data' is the preferred approach, in some case you may
    # need to place data files outside of your packages. See:
    # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa
    # In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
    # data_files=[('my_data', ['data/data_file'])],
    data_files=[],

    # To provide executable scripts, use entry points in preference to the
    # "scripts" keyword. Entry points provide cross-platform support and allow
    # pip to create the appropriate form of executable for the target platform.
    entry_points={
        'console_scripts': [
            'mypackage-run=mypackage:main',
        ],
    },
)
Sam Thomas
  • 647
  • 7
  • 25

1 Answers1

2

Users should not edit a file that is included in your distribution, and neither should they create any new files in the directory where your distribution gets installed.

A common pattern is to use a file in the homedir, e.g. ~/.myapp.cfg for any customizations, and then just distribute some sensible default configuration with your app.

Your app will check for the presence of the user configuration, but the app should not require the presence of a custom config in order to run. You can make the decision about whether you want to "layer" the user config on top of the default config, or simply use it in preference to the default config.

Make sure the file format and expected location of the user configuration is clearly documented.

wim
  • 338,267
  • 99
  • 616
  • 750
  • I was afraid i would get comments about editing files included with the distribution. Regardless, If i assume, the distribution is the one that installed myapp.cfg in the home directory and the user edited it, is there a way to leave this file as is and not replace with the default myapp.cfg on a pip ugrade? – Sam Thomas Nov 14 '17 at 23:30
  • 1
    It will depend on your `setup.py`, which you haven't included in the question (please add it). Are you using `distutils` or `setuptools`? Which version? – wim Nov 15 '17 at 00:39
  • I have included my setup.py. I took the file from pypa's git and they recommend using setup tools, which I use. I'm not sure how the version affects this but it is 36.6.0 – Sam Thomas Nov 15 '17 at 23:30
  • 2
    I just tried it for about 2 hours, now I give up. I'm convinced now you can't do it (at least not without intrusive hacks). You might consider to make a [post-install script](https://stackoverflow.com/q/17806485/674039) instead of using `package_data`. Or just abandon the idea. – wim Nov 16 '17 at 06:48
  • Damn. Thanks a lot for trying :) – Sam Thomas Nov 16 '17 at 20:09
  • This answer is correct. You should not be doing this, but should put user configuration elsewhere. In many cases, the user won't even have permission to edit your package files. – Paul Moore Nov 18 '17 at 10:53