[Distutils] Best practices to package a desktop application
PJ Eby
pje at telecommunity.com
Thu Dec 29 20:47:44 CET 2011
On Thu, Dec 29, 2011 at 10:04 AM, Jonathan Ballet <jon at multani.info> wrote:
> 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. ;-)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/distutils-sig/attachments/20111229/dc9be7f1/attachment.html>
More information about the Distutils-SIG
mailing list