Starting with distutils.
Once you've collected all the bits and
bobs for your application, you start using distutils by writing
a special Python script, customarily named
setup.py. You can make your
setup.py script as complex as you want, but
typically it is quite simple.
The setup.py script will
then call setup from
distutils.core with lots of arguments, including
meta-data about the application or module to install, and a list
of stuff to install.
The developer uses the
setup.py script to create the package, and
the user uses it to install the package.
setup.py
Example 26-2. setup.py - a sample setup script
#!/usr/bin/env python
from distutils.core import setup
setup(name = "kalam",
version = "1.0",
description = "Kalam - the extensible Python editor",
author = "Boudewijn Rempt",
author_email = "boud@rempt.xs4all.nl",
url = "http://www.valdyas.org",
packages = ["charmap",
"kalamlib",
"typometer",
"workspace",
""],
data_files = [("kalam/data", ["data/Blocks.txt"]),
("kalam/pixmaps", ["pixmaps/listspace.png",
"pixmaps/splitspace.png",
"pixmaps/stackspace.png",
"pixmaps/tabmanager.png",
"pixmaps/workspace.png"])],
scripts = ["kalam","kalam.bat"],
long_description = """
Kalam is a plain-text editor. It is written in Python using
the PyQt GUI toolkit as an example and tutorial for the book
GUI programming with Python and Qt, published by Opendocs.
"""
)
The setup.py is the
place to specify all executable parts of your application, and
some metadata. Let's examine all parts:
name: the name of
the application
version: the
version number (major, minor, wee number)
description: a
short description of the application
author: the
person responsible for the application
author_email: his
email address
url: website
where the application is hosted
packages: a list
of Python modules (directories that contain a set of
Python files listed in a __init__.py
file). In the case of Kalam
these are the modules for the character map, the
type-o-meter and the set of workspace options. The
additional module, kalamlib, contains all the real
Kalam code.
py_modules: a
list of Python files. Note that if you include both the
packages and
thepy_modules keyword only the latter
will be used.
data_files: this
is a list of files that are not executable code. These
files will be installed in a default place, like
/usr/share on Linux. You must also
include all these files in MANIFEST.in,
otherwise they won't be packaged.
scripts: this is
a list of python script files. If you use
#!/usr/bin/python as the first line of a script to make it
executable on Unix, Distutils will change that to the
location of Python on the user's machine.
long_description:
a longer description of the application. This is used when
you create an rpm package.
There are other options more concerned with
distributing C or C++ extension modules you have
created. I don't cover them here.
Finally, a word of warning: if you are experimenting with
setup.py, you will notice that a file called
MANIFEST has been created. Always remove this
file after creating a distribution. It is a kind of
cache that lists the set of files that should be included;
if you change this set, distutils will still read
MANIFEST instead of your changes in
setup.py.
MANIFEST.in
Despite the data_files option to
setup(), it is still necessary to provide
a second file that contains a list of extra, non-Python
files that need to be distributed. This file is called
MANIFEST.in (mind the capitalization),
and employs its own set of keywords to specify files to
include or exclude.
Example 26-3. MANIFEST.in
include kalam
include kalam.bat
recursive-include data *
recursive-include pixmaps *
recursive-include dialogs *
Here, we include the kalam starter script
and the kalam.bat and batch file. Then we
recursively include everything in the directories
data, pixmaps and
dialogs. (The latter is not absolutely
necessary for running the application, but it can't hurt to
give people access to our dialog designs.)
The options available for
MANIFEST.in are:
include pat1 pat2 ...
exclude pat1 pat2 ...
recursive-include dir pat1 pat2 ...
recursive-exclude dir pat1 pat2 ...
global-include pat1 pat2 ...
global-exclude pat1 pat2 ...
prune dir
graft dir
setup.cfg
The setup.py script takes myriad
command-line options. You can also create a
setup.cfg file that contains the most
important options. Amongst those options are a number that tell the
installer to install the application in a
specific place. The user might need to edit these to reflect
his preferences. For Unix, a good default is:
[install]
install_lib=/usr/local/share/kalam
install_data=/usr/local/share/kalam
install_scripts=/usr/local/bin
All Python files (everything that is mentioned in the
py_modules or packages
argument in setup.py) will be installed
in the install_lib directory. Everything that is mentioned in
the data_files argument will be installed
in the install_data directory. Likewise, everything that is
included in the scripts argument will be
installed in install_scripts.
Creating the source distribution
We are now ready to create the source distribution. This is a
simple, one-line command:
boud@calcifer:~/src/kalam > python setup.py sdist
The distutils will then spew a lot of text on the screen,
and deliver your package in a subdirectory named
dist:
boudewijn@maldar:~/doc/pyqt/ch18/kalam > python setup.py sdist
running sdist
reading manifest template 'MANIFEST.in'
writing manifest file 'MANIFEST'
creating kalam-1.0
creating kalam-1.0/charmap
creating kalam-1.0/data
creating kalam-1.0/dialogs
creating kalam-1.0/kalamlib
creating kalam-1.0/pixmaps
creating kalam-1.0/typometer
creating kalam-1.0/workspace
making hard links in kalam-1.0...
hard linking README -> kalam-1.0
hard linking edmund.py -> kalam-1.0
hard linking kalam -> kalam-1.0
hard linking kalam.bat -> kalam-1.0
hard linking setup.cfg -> kalam-1.0
hard linking setup.py -> kalam-1.0
hard linking sitecustomize.py -> kalam-1.0
hard linking startup.py -> kalam-1.0
hard linking charmap/__init__.py -> kalam-1.0/charmap
hard linking charmap/charmap.py -> kalam-1.0/charmap
hard linking data/Blocks.txt -> kalam-1.0/data
hard linking dialogs/frmfindreplace.ui -> kalam-1.0/dialogs
hard linking dialogs/frmsettings.ui -> kalam-1.0/dialogs
hard linking kalamlib/__init__.py -> kalam-1.0/kalamlib
hard linking kalamlib/configtest.py -> kalam-1.0/kalamlib
hard linking kalamlib/dlgfindreplace.py -> kalam-1.0/kalamlib
hard linking kalamlib/dlgsettings.py -> kalam-1.0/kalamlib
hard linking kalamlib/docmanager.py -> kalam-1.0/kalamlib
hard linking kalamlib/docmanagertest.py -> kalam-1.0/kalamlib
hard linking kalamlib/frmfindreplace.py -> kalam-1.0/kalamlib
hard linking kalamlib/frmsettings.py -> kalam-1.0/kalamlib
hard linking kalamlib/kalamapp.py -> kalam-1.0/kalamlib
hard linking kalamlib/kalamconfig.py -> kalam-1.0/kalamlib
hard linking kalamlib/kalamdoc.py -> kalam-1.0/kalamlib
hard linking kalamlib/kalamview.py -> kalam-1.0/kalamlib
hard linking kalamlib/macromanager.py -> kalam-1.0/kalamlib
hard linking kalamlib/macromanagertest.py -> kalam-1.0/kalamlib
hard linking kalamlib/main.py -> kalam-1.0/kalamlib
hard linking kalamlib/resources.py -> kalam-1.0/kalamlib
hard linking pixmaps/fileprint.xpm -> kalam-1.0/pixmaps
hard linking pixmaps/find.png -> kalam-1.0/pixmaps
hard linking pixmaps/listspace.png -> kalam-1.0/pixmaps
hard linking pixmaps/listspace.xpm -> kalam-1.0/pixmaps
hard linking pixmaps/splitspace.png -> kalam-1.0/pixmaps
hard linking pixmaps/splitspace.xpm -> kalam-1.0/pixmaps
hard linking pixmaps/stackspace.png -> kalam-1.0/pixmaps
hard linking pixmaps/stackspace.xpm -> kalam-1.0/pixmaps
hard linking pixmaps/tabmanager.png -> kalam-1.0/pixmaps
hard linking pixmaps/tabmanager.xpm -> kalam-1.0/pixmaps
hard linking pixmaps/workspace.png -> kalam-1.0/pixmaps
hard linking pixmaps/workspace.xpm -> kalam-1.0/pixmaps
hard linking typometer/__init__.py -> kalam-1.0/typometer
hard linking typometer/typometer.py -> kalam-1.0/typometer
hard linking workspace/__init__.py -> kalam-1.0/workspace
hard linking workspace/listspace.py -> kalam-1.0/workspace
hard linking workspace/splitspace.py -> kalam-1.0/workspace
hard linking workspace/stackspace.py -> kalam-1.0/workspace
hard linking workspace/tabmanager.py -> kalam-1.0/workspace
hard linking workspace/workspace.py -> kalam-1.0/workspace
creating dist
tar -cf dist/kalam-1.0.tar kalam-1.0
gzip -f9 dist/kalam-1.0.tar
removing 'kalam-1.0' (and everything under it)
boudewijn@maldar:~/doc/pyqt/ch18/kalam >
That's it—a nice, clean and complete source distribution
of Kalam. You can generate both zip
archives and gzipped tarballs by providing options on the
command line:
boudewijn@maldar:~/doc/pyqt/ch18/kalam > python setup.py sdist --formats=gztar,zip
The options are zip, gztar, bztar, ztar and tar, for
zipfiles, gzipped tarfiles, bzipped tarfiles, compressed
tarfiles and plain tar files.
Installing a source archive
Installing a source archive is a simple matter of
unpacking the archive and executing the following command:
boudewijn@maldar:~/doc/pyqt/ch18/kalam/dist/kalam-1.0 > python setup.py install
Distutils will copy everything to the location
designated in setup.cfg, and
kalam will be ready to run!.