+###--------------------------------------------------------------------------
+### Adding new commands.
+
+CMDS = {}
+
+class CommandClass (type):
+ """
+ Metaclass for command classes: automatically adds them to the `CMDS' map.
+ """
+ def __new__(cls, name, supers, dict):
+ c = super(CommandClass, cls).__new__(cls, name, supers, dict)
+ try: name = c.NAME
+ except AttributeError: pass
+ else: CMDS[name] = c
+ return c
+
+class Command (DC.Command, object):
+ """
+ Base class for `mdwsetup' command classes.
+
+ This provides the automatic registration machinery, via the metaclass, and
+ also trivial implementations of various responsibilities of `DC.Command'
+ methods and attributes.
+ """
+ __metaclass__ = CommandClass
+ user_options = []
+ def initialize_options(me): pass
+ def finalize_options(me): pass
+ def run_subs(me):
+ for s in me.get_sub_commands(): me.run_command(s)
+
+###--------------------------------------------------------------------------
+### Some handy new commands.
+
+class distdir (Command):
+ NAME = 'distdir'
+ description = "print the distribution directory name to stdout"
+ def run(me):
+ d = me.distribution
+ print '%s-%s' % (d.get_name(), d.get_version())
+
+class build_gen(Command):
+ """
+ Generate files, according to the `genfiles'.
+
+ The `genfiles' keyword argument to `setup' lists a number of objects which
+ guide the generation of output files. These objects must implement the
+ following methods.
+
+ clean(DRY_RUN_P) Remove the output files.
+
+ gen(DRY_RUN_P) Generate the output files, if they don't exist or are
+ out of date with respect to their prerequisites.
+
+ If DRY_RUN_P is true then the methods must not actually do anything with a
+ lasting effect, but should print progress messages as usual.
+ """
+ NAME = 'build_gen'
+ description = "build generated source files"
+ def run(me):
+ d = me.distribution
+ for g in d.genfiles: g.gen(dry_run_p = me.dry_run)
+
+from distutils.command.build import build as _build
+class build (_build, Command):
+ ## Add `build_gen' early in the list of subcommands.
+ NAME = 'build'
+ sub_commands = [('build_gen', lambda me: me.distribution.genfiles)]
+ sub_commands += _build.sub_commands
+
+class clean_gen(Command):
+ """
+ Remove the generated files, as listed in `genfiles'.
+
+ See the `build_gen' command for more detailed information.
+ """
+ NAME = 'clean_gen'
+ description = "clean generated source files"
+ def run(me):
+ d = me.distribution
+ for g in d.genfiles: g.clean(dry_run_p = me.dry_run)
+
+class clean_others(Command):
+ """
+ Remove the files listed in the `cleanfiles' argument to `setup'.
+ """
+ NAME = 'clean_others'
+ description = "clean miscellaneous output files"
+ def run(me):
+ d = me.distribution
+ for f in d.cleanfiles:
+ if not OS.path.exists(f): continue
+ DL.log(DL.INFO, "delete `%s'", f)
+ if not me.dry_run: OS.remove(f)
+
+from distutils.command.clean import clean as _clean
+class clean (_clean, Command):
+ ## Add `clean_gen' and `clean_others' to the list of subcommands.
+ NAME = 'clean'
+ sub_commands = [('clean_gen', lambda me: me.distribution.genfiles),
+ ('clean_others', lambda me: me.distribution.cleanfiles)]
+ sub_commands += _clean.sub_commands
+ def run(me):
+ me.run_subs()
+ _clean.run(me)
+
+from distutils.command.sdist import sdist as _sdist
+class sdist (_sdist, Command):
+ ## Write a `RELEASE' file to the output, if we extracted the version number
+ ## from version control. Also arrange to dereference symbolic links while
+ ## copying. Symlinks to directories will go horribly wrong, so don't do
+ ## that.
+ NAME = 'sdist'
+ def make_release_tree(me, base_dir, files):
+ _sdist.make_release_tree(me, base_dir, files)
+ d = me.distribution
+ if d._auto_version_p:
+ v = d.metadata.get_version()
+ DL.log(DL.INFO, "write `RELEASE' file: %s" % v)
+ with open(OS.path.join(base_dir, 'RELEASE'), 'w') as f:
+ f.write('%s\n' % v)
+ def copy_file(me, infile, outfile, link = None, *args, **kw):
+ if OS.path.islink(infile): link = None
+ return _sdist.copy_file(me, infile, outfile, link = link, *args, **kw)
+
+###--------------------------------------------------------------------------
+### Our own version of `setup'.
+
+class Dist (DC.Distribution):
+ ## Like the usual version, but with some additional attributes to support
+ ## our enhanced commands.
+ def __init__(me, attrs = None):
+ me.genfiles = []
+ me.cleanfiles = []
+ me._auto_version_p = False
+ DC.Distribution.__init__(me, attrs)
+ if me.metadata.version is None:
+ me.metadata.version = auto_version(writep = False)
+ me._auto_version_p = True
+ me.cleanfiles = set(me.cleanfiles)
+ me.cleanfiles.add('MANIFEST')
+
+def setup(cmdclass = {}, distclass = Dist, **kw):
+ ## Like the usual version, but provides defaults more suited to our
+ ## purposes.
+ cmds = dict()
+ cmds.update(CMDS)
+ cmds.update(cmdclass)
+ DC.setup(cmdclass = cmds, distclass = distclass, **kw)
+