mkpkg: Helper to create setup.py for your projects. (tummy.com, ltd. Journal Entry)
tummy.com: we do linux

Tuesday March 02, 2010 at 01:04
Subject: mkpkg: Helper to create setup.py for your projects.
Keywords: Packaging, Python
Posted by: Sean Reifschneider

At the PyCon sprints I mostly worked on my write-up for the conference networking, and other administratrivia related to PyCon 2010 and getting ready for 2011. However, I did achieve one thing, and that's "mkpkg".

During the Language Summit we were speaking about packaging, and Guido said that he usually doesn't create packages. And I felt his pain, because I usually put it off a long as possible too. But from that I decided that I wanted to build a helper to make setting up the package files a no-brainer.

A couple of days into the sprint, I had something that was a good start. Continue reading for more details.

First of all, yes I know that setup.py is being done away with. My expectation is that when it goes to setup.cfg, or whatnot, that mkpkg will follow and write the new style configs. mkpkg is checked into the distutils2 repository, and so it should go with distutils when it's ready.

Until then you can use mkpkg by running:

wget ftp://ftp.tummy.com/pub/tummy/mkpkg.py/mkpkg.py
python mkpkg.py

Or, when it gets included in distutils2:

python -m distutils2.mkpkg

The latter syntax was suggested by Tarek Ziade'

Here's a sample session:

guin:/tmp$ cd /tmp
guin:/tmp$ mkdir testpkg
guin:/tmp$ cd testpkg   
guin:testpkg$ mkdir -p src/testgoat
guin:testpkg$ touch src/testgoat/__init__.py
guin:testpkg$ wget ftp://ftp.tummy.com/pub/tummy/mkpkg.py/mkpkg.py
2010-03-02 00:50:25 (337 KB/s) - `mkpkg.py' saved [36462]
ckage name [testpkg]:
Current version number: ?
======================================================================
Version number of the software, typically 2 or 3 numbers separated by dots
such as "1.00", "0.6", or "3.02.01".  "0.1.0" is recommended for initial
development.
======================================================================
Current version number: 0.1.0
Package description: 
   >A simple package to demonstrate the use of mkpkg.
Author name [Sean Reifschneider]: 
Author e-mail address [jafo@tummy.com]: 
Project URL: 
Do you want to set Trove classifiers?: n
Wrote "setup.py".
guin:testpkg$

Note that it used the current directory name for the package name. If the directory name had the version in it, like "testpkg-0.1.0", it would have used that as the default. Also note that I pressed "?" to get help on the version.

The resulting setup.py is:

#!/usr/bin/env python

from distutils.core import setup

from sys import version
if version < '2.2.3':
    from distutils.dist import DistributionMetadata
    DistributionMetadata.classifiers = None
    DistributionMetadata.download_url = None
setup(name = 'testpkg',
        version = '0.1.0',
        description = 'A simple package to demonstrate the use of mkpkg.',
        author = 'Sean Reifschneider',
        author_email = 'jafo@tummy.com',
        classifiers = [
              'Programming Language :: Python :: 2',
           ],
        packages = ['testgoat'],
        package_dir = {'testgoat': 'src/testgoat'},
        #scripts = ['path/to/script']
        )

Note that it picked up the testgoat package (via the presence of src/testgoat/__init__.py), and it also detected that it was Python version 2. If I had "#!/usr/bin/env python3", it would have listed it as a Python 3 package. Finally, it stores my name and e-mail information in "~/.mkpkgpy" -- it will ask you the first time you run it.

One thing I skipped over is the trove classifiers. mkpkg has a helper for selecting the trove categories, here's an example of it:

Do you want to set Trove classifiers?: y
Please select the project status:

1 - Planning
2 - Pre-Alpha
3 - Alpha
4 - Beta
5 - Production/Stable
6 - Mature
7 - Inactive

Status: 3
What license do you use: python
Matching licenses:

   1) License :: OSI Approved :: Python License (CNRI Python License)
   2) License :: OSI Approved :: Python Software Foundation License

Type the number of the license you wish to use or ? to try again:: 2
Do you want to set other trove identifiers [n]: y
Do you want to set items under
   "Development Status" (7 sub-items) [n]:  
Do you want to set items under
   "Environment" (9 sub-items) [n]: y
Do you want to set items under
   "Console" (4 sub-items) [n]: y
Add "Environment :: Console" :: Curses [n]: 
Add "Environment :: Console" :: Framebuffer [n]: 
Add "Environment :: Console" :: Newt [n]: 
Add "Environment :: Console" :: svgalib [n]: 
Add "Environment" :: Handhelds/PDA's [n]: 
Do you want to set items under
   "MacOS X" (3 sub-items) [n]: 
Add "Environment" :: No Input/Output (Daemon) [n]: y
Add "Environment" :: Other Environment [n]: 
Add "Environment" :: Plugins [n]: 
Do you want to set items under
   "Web Environment" (3 sub-items) [n]: 
Add "Environment" :: Win32 (MS Windows) [n]: 
Do you want to set items under
   "X11 Applications" (4 sub-items) [n]: 
Do you want to set items under
   "Framework" (16 sub-items) [n]: 
Do you want to set items under
   "Intended Audience" (14 sub-items) [n]: y
Add "Intended Audience" :: Customer Service [n]:
Add "Intended Audience" :: Developers [n]: y
Add "Intended Audience" :: Education [n]: 
Add "Intended Audience" :: End Users/Desktop [n]: 
Add "Intended Audience" :: Financial and Insurance Industry [n]: 
Add "Intended Audience" :: Healthcare Industry [n]: 
Add "Intended Audience" :: Information Technology [n]: 
Add "Intended Audience" :: Legal Industry [n]: 
Add "Intended Audience" :: Manufacturing [n]: 
Add "Intended Audience" :: Other Audience [n]: 
Add "Intended Audience" :: Religion [n]: 
Add "Intended Audience" :: Science/Research [n]: 
Add "Intended Audience" :: System Administrators [n]: 
Add "Intended Audience" :: Telecommunications Industry [n]: 
Do you want to set items under
   "License" (15 sub-items) [n]: 
Do you want to set items under
   "Natural Language" (52 sub-items) [n]: 
Do you want to set items under
   "Operating System" (10 sub-items) [n]: 
Do you want to set items under
   "Programming Language" (54 sub-items)
    [n]: 
Do you want to set items under
   "Topic" (24 sub-items) [n]: 
Wrote "setup.py".

This probably does need some improvement, but it's a start. The first couple of questions, about project status (I selected Beta), and the license are the best helpers. The rest of it is just navigating the Trove tree. Note that for selecting the license I said "python" and it looked at the available licenses and selected two possible choices for me to pick from.

So, that's what I've got so far.
(Post Reply)

Comment
Marius Gedminas
Subject: easy_install mkpkg?
/me likes

It would be nice if we could easy_install wcfqfu without having to remember long FTP URLs and without having to wait for distutils2 to appear in some future release of Python.

Comment
Michael Mulich (pumazi)
Subject: PasteScript Difference
Do you feel this is any different from using PasteScript?

I've used 'paster create -t basic_package ' for the past year to do exactly what you are doing here. The only difference I can see off the top of my head is that your implementation doesn't have the Paste dependency.

Some could argue that PasteScript is over engineered, but that's what makes it extendable. For instance, the basic_namespace template (e.g. `paster create -t basic_namespace my.package') is built from the basic_package template. And there are other packaging templates built from that for more specific cases.

Comment
merwok
Subject: Maintenance
Hello

The mkpkg script is now included in Distutils2. Do you still intend to sync it and serve it or are you going to point people to Distutils2?

Regards

Comment
Author: Sean Reifschneider
Subject: I'll point people at Distutils2.
I plan to point people to Distutils2. My copy was really meant to be used in the interim until Distutils2 was available.

Sean