Your OpenSource Publisher™
Products  |  Where to buy  |  Retailers  |  FAQ  |  Write for Us.  |  Contact Us.

Boudewijn Rempt

ISBN: 0-97003300-4-4
Available from bookstores everywhere or you can order it here.

You can download the source files for the book (code / eps) here.


Starting with distutils.

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!.