Best practices to package a desktop application
Hi, I hav a desktop application which currently runs only on Linux using pyGtk, and is packaged using setuptools/distribute. It ships with a number of non-Python files: * documentation (README, Changelog, Authors, etc.) * .desktop file * application specific's icons * one man file * translation files * and one executable script The setup.py file looks like this so far: setup( name='myapp', ... packages=["myapp"], package_dir={"myapp": "myapp/"}, data_files=[ ('share/myapp', ['README', 'Changelog', 'Authors']), ('share/applications', ['myapp.desktop']), ('share/pixmaps', glob.glob('myapp/pixmaps/*')), ('share/man/man1', ['myapp.1']), ('share/locale/fr/LC_MESSAGES', ['mo/fr/myapp.mo']), ... numerous other translation files ... ], entry_points={'console_scripts': ['myapp=myapp:run']}, ) but I somehow have a bad feeling about this, except for the entry point (which does a great job). When I run ``python setup.py install --prefix="local"``, everything gets installed into ``site-packages/myapp/``, Python files and data files, which seems to be a feature of setuptools/distribute over plain Distutils, whereas it seems to be "cleaner" to split things as described by the ``data_files`` setting (and AFAIK, Distutils does just that). To be clear, I end up with install/lib/python2.7/site-packages/myapp.egg/myapp.py ... install/lib/python2.7/site-packages/myapp.egg/share/myapp/README ... install/lib/python2.7/site-packages/myapp.egg/share/pixmaps/myapp.png ... install/lib/python2.7/site-packages/myapp.egg/share/locale/fr/LC_MESSAGES/myapp.mo ... Whereas I "think" I would like to have this instead, which looks more organized to me: install/lib/python2.7/site-packages/myapp.egg/myapp.py ... install/share/myapp/README ... install/share/pixmaps/myapp.png ... install/share/locale/fr/LC_MESSAGES/myapp.mo ... Actually, someone reported this "bug" to me, as he was expecting the latter whereas he got the former. Also, the application currently uses a custom method to find the location of those data files (mainly the icons which are used at run-time). It does a "terrible" job of trying several well-known locations until it either reaches the file or fails with a laconic error. I guess using ``pkg_resources`` data-access API would be much better, right? Finally, I'm also concerned about Linux distribution packagers, and I would like to package the application so that it also useful and easy for them to repackage and distribute it. After reading setuptools/distribute and distutils documentations, I'm still not what is the best way to proceed. Any hints would be greatly appreciated. Regards, Jonathan
On Thu, Dec 29, 2011 at 10:04 AM, Jonathan Ballet
Hi,
I hav a desktop application which currently runs only on Linux using pyGtk, and is packaged using setuptools/distribute.
It ships with a number of non-Python files:
* documentation (README, Changelog, Authors, etc.) * .desktop file * application specific's icons * one man file * translation files * and one executable script
The setup.py file looks like this so far:
setup( name='myapp', ... packages=["myapp"], package_dir={"myapp": "myapp/"}, data_files=[ ('share/myapp', ['README', 'Changelog', 'Authors']), ('share/applications', ['myapp.desktop']), ('share/pixmaps', glob.glob('myapp/pixmaps/*')), ('share/man/man1', ['myapp.1']), ('share/locale/fr/LC_MESSAGES', ['mo/fr/myapp.mo']), ... numerous other translation files ...
], entry_points={'console_scripts': ['myapp=myapp:run']}, )
but I somehow have a bad feeling about this, except for the entry point (which does a great job).
When I run ``python setup.py install --prefix="local"``, everything gets installed into ``site-packages/myapp/``, Python files and data files, which seems to be a feature of setuptools/distribute over plain Distutils, whereas it seems to be "cleaner" to split things as described by the ``data_files`` setting (and AFAIK, Distutils does just that).
To be clear, I end up with
install/lib/python2.7/site-packages/myapp.egg/myapp.py ... install/lib/python2.7/site-packages/myapp.egg/share/myapp/README ... install/lib/python2.7/site-packages/myapp.egg/share/pixmaps/myapp.png ...
install/lib/python2.7/site-packages/myapp.egg/share/locale/fr/LC_MESSAGES/myapp.mo ...
Whereas I "think" I would like to have this instead, which looks more organized to me:
install/lib/python2.7/site-packages/myapp.egg/myapp.py ... install/share/myapp/README ... install/share/pixmaps/myapp.png ... install/share/locale/fr/LC_MESSAGES/myapp.mo ...
Actually, someone reported this "bug" to me, as he was expecting the latter whereas he got the former.
Also, the application currently uses a custom method to find the location of those data files (mainly the icons which are used at run-time). It does a "terrible" job of trying several well-known locations until it either reaches the file or fails with a laconic error. I guess using ``pkg_resources`` data-access API would be much better, right?
Well, it'd certainly be One Obvious Way to do it. ;-) The way I look at it is, if the "data" file is really just a code constant (i.e., not user-modifiable, nor modified by the program), then it's not really data, it's part of the code. A "resource" rather than data. That's what the pkg_resources API is for: resources. Now, if it's data or configuration -- something the user or program will touch -- then resources don't cut it. You need a way to set that stuff up. Same for documentation, unless it's a program-served resource. Setuptools doesn't handle those so well; eggs and easy_install were designed for application *plugins* more than applications; it was assumed that when you install the self-contained .egg, the application platform would provide documentation browsing and configuration support. So, there was no real provision for installing things to multiple places; even scripts were a bit of an afterthought. Finally, I'm also concerned about Linux distribution packagers, and I
would like to package the application so that it also useful and easy for them to repackage and distribute it.
If you actually build a system package (e.g. via bdist_rpm), you'll notice that your package will actually be installed the way you want: the data files will go to the right place. That's because "setup.py install --root /somepath" or "setup.py install --single-version-externally-managed" will use distutils conventions for installation. So, don't worry about the system packagers, you're doing it right (enough) with your current mechanism. After reading setuptools/distribute and distutils documentations, I'm
still not what is the best way to proceed. Any hints would be greatly appreciated.
Based on what you're trying to accomplish, I'd suggest: 1. Use pkg_resources to access constant "resource" files that are not user-changeable 2. Leave configuration, data, or documentation files as 'data_files' in your setup.py 3. If your package doesn't need easy_install support (i.e., it has no dependencies to download), add a setup.cfg with: [install] single_version_externally_managed = 1 record = RECORD And tell people to install it using "setup.py install". This will install it in a flat (no .egg subdirectory) fashion, and with data files to the share/ location you expect. If you *do* need easy_install support, then it's a bit more complex, so I'm not going to spell that out unless you first say that you do need it. ;-)
participants (2)
-
Jonathan Ballet
-
PJ Eby