On Nov 12, 2009, at 12:42 PM, John Kleint wrote:

I have the start of such a document, derived from my own recent
experience pulling together all the information needed to release a
new Python project.  It's aimed at people new to packaging and
possibly open source in general, so it's broader than just packaging.
It includes things like basic file layout, unit testing, Pylint,
getting started with Sphinx, a sample (distutils) setup.py, and how to
register with PyPI.  I try to pull together all the info a novice
would need to have a reasonable shot at sharing their code.  It's by
no means all-encompassing (e.g. no mention of native extensions), but
perhaps someone would be willing to write a complimentary advanced
packaging howto.  You can find it at:

http://infinitemonkeycorps.net/docs/pph/

Let me know what you think.


It's a good start, but a few critques on the packaging section:

 * Avoid importing your package before you've installed it.

Importing a package works fine for packages which have no dependencies, but once your package depends upon other packages you can't use this technique. It's better to teach people how to write setup.py scripts which don't import the package so that their setup.py's can be consistent once they do write packages with dependencies. There are lots of cases where the assumptions of the configuration of a developer's environment where dependencies are installed that won't work for other people trying to install such a package, which leads to setup.py files which don't work.

One example for handling the long_description field can be done with (there are lots of variants on this, and you can just call open() for a single text file:

def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()

long_description=read(
    read('README.txt')
    + '\n' +
    'Detailed Documentation\n'
    '**********************\n'
    + '\n' +
    'src/some-other-file.txt',
)


 * download_url field is not necessary.

Libraries are often installed automatically by tools (buildout, pip, easy_install). This work best if the downloads are in a consistent structure (e.g. on PyPI). If releases are made to PyPI, then you don't need a download_url to get to another place where the file can be downloaded. The field is also prone to mistakes, since easy_install will follow the download URL and screen-scrape that page looking for a download link. Which can lead to older or wrong versions of the package being downloaded. Basically it just causes room for errors, and is just one extra step that you need to do to create a package, so why do it?

 * package_dir location.

This is a very minor point, but I find putting the source in a directory named after the module or package which isn't the module or package confusing. A common alternative is to use 'src' as the name for the source directory. Then that location can be consistent from package to package.

 * provides (and requires) are scheduled for deprecation

These fields don't make any sense. If you are listing the imports that your package needs, you need to list the name of the distribution which provides those packages, not the names of the imports that your code is using. setuptools (or now distribute) lets you use an 'install_requires' field, and this fields is also likely to be in Distutils in the next Python release.


 * Use a tool to help automate releases

Creating each release requires a lot of manual changes here and there (bump the version, update the changelog, run sdist, upload to pypi). In the spirit of "release early, release often", I like to use a tool to automate releases, and also helps establish a few more common conventions between Python projects. I'm using zest.releaser for this ATM (shameless plug, since I'm also a contributor to the project):

   http://pypi.python.org/pypi/zest.releaser




_______________________________________________
Distutils-SIG maillist  -  Distutils-SIG@python.org
http://mail.python.org/mailman/listinfo/distutils-sig

Reply via email to