[py-dev] Moving py-lib to setuptools

Ian Bicking ianb at colorstudy.com
Mon Nov 21 21:16:53 CET 2005


Does anyone have an opinion on setup.py and how py-lib is packaged?  It 
seems like it was put in place some time ago, and py hasn't really been 
formally released since then.

Anyway, I think a lot of the hackish parts are dealt with by setuptools. 
  setuptools.find_packages() fills out the packages, and its backport of 
package_data deals with non-Python files, and paste.util.finddata can be 
copied in to deal with enumerating the package data.  setuptools has 
some possibly useful script generation capability, but that doesn't need 
to be used.  Maybe it should be, though; it creates a .exe file on 
Windows for each script.  I don't know know it would interact with the 
"py.test" name; I doubt that's been considered on Windows, and probably 
setuptools should remove dots from scripts on Windows.

I was going to upload the setup.py file to use setuptools, but I lost my 
svn password, so I'll just attach them for now.  There's probably some 
other things I'd add to fully convert it, like just removing the 
download URL and using the Cheese Shop for file distribution, and 
perhaps adding a setup.cfg that append svn revisions to the versions of 
distributions made from the trunk.

-- 
Ian Bicking  /  ianb at colorstudy.com  /  http://blog.ianbicking.org
-------------- next part --------------
# Note: you may want to copy this into your setup.py file verbatim, as
# you can't import this from another package, when you don't know if
# that package is installed yet.

import os
import sys
from fnmatch import fnmatchcase
from distutils.util import convert_path

# Provided as an attribute, so you can append to these instead
# of replicating them:
standard_exclude = ('*.py', '*.pyc', '*~', '.*', '*.bak')
standard_exclude_directories = ('.*', 'CVS', '_darcs', './build',
                                './dist', 'EGG-INFO', '*.egg-info')

def find_package_data(
    where='.', package='',
    exclude=standard_exclude,
    exclude_directories=standard_exclude_directories,
    only_in_packages=True,
    show_ignored=False):
    """
    Return a dictionary suitable for use in ``package_data``
    in a distutils ``setup.py`` file.

    The dictionary looks like::

        {'package': [files]}

    Where ``files`` is a list of all the files in that package that
    don't match anything in ``exclude``.

    If ``only_in_packages`` is true, then top-level directories that
    are not packages won't be included (but directories under packages
    will).

    Directories matching any pattern in ``exclude_directories`` will
    be ignored; by default directories with leading ``.``, ``CVS``,
    and ``_darcs`` will be ignored.

    If ``show_ignored`` is true, then all the files that aren't
    included in package data are shown on stderr (for debugging
    purposes).

    Note patterns use wildcards, or can be exact paths (including
    leading ``./``), and all searching is case-insensitive.
    """
    
    out = {}
    stack = [(convert_path(where), '', package, only_in_packages)]
    while stack:
        where, prefix, package, only_in_packages = stack.pop(0)
        for name in os.listdir(where):
            fn = os.path.join(where, name)
            if os.path.isdir(fn):
                bad_name = False
                for pattern in exclude_directories:
                    if (fnmatchcase(name, pattern)
                        or fn.lower() == pattern.lower()):
                        bad_name = True
                        if show_ignored:
                            print >> sys.stderr, (
                                "Directory %s ignored by pattern %s"
                                % (fn, pattern))
                        break
                if bad_name:
                    continue
                if os.path.isfile(os.path.join(fn, '__init__.py')):
                    if not package:
                        new_package = name
                    else:
                        new_package = package + '.' + name
                    stack.append((fn, '', new_package, False))
                else:
                    stack.append((fn, prefix + name + '/', package, only_in_packages))
            elif package or not only_in_packages:
                # is a file
                bad_name = False
                for pattern in exclude:
                    if (fnmatchcase(name, pattern)
                        or fn.lower() == pattern.lower()):
                        bad_name = True
                        if show_ignored:
                            print >> sys.stderr, (
                                "File %s ignored by pattern %s"
                                % (fn, pattern))
                        break
                if bad_name:
                    continue
                out.setdefault(package, []).append(prefix+name)
    return out

if __name__ == '__main__':
    import pprint
    pprint.pprint(
        find_package_data(show_ignored=True))
-------------- next part --------------
from setuptools import setup, find_packages
from finddata import find_package_data

setup(
    name="py",
    version="0.8.0-alpha2",
    description="py.test and the py lib",
    long_description="""\
The py lib is a development support library featuring
py.test, an interactive testing tool which supports
unit-testing with practically no boilerplate.""",
    url="http://codespeak.net/py",
    author="Holger Krekel & others",
    author_email="hpk at merlinux.de",
    license="MIT license",
    download_url="http://codespeak.net/download/py/py-0.8.0-alpha2.tar.gz",
    packages=find_packages(),
    package_data=find_package_data(),
    scripts=['py/bin/_findpy.py',
             'py/bin/_makepyrelease.py',
             'py/bin/py.cleanup',
             'py/bin/py.countloc',
             'py/bin/py.lookup',
             'py/bin/py.rest',
             'py/bin/py.test',
             'py/bin/pytest.cmd'],
    )


More information about the py-dev mailing list