[Twisted-Python] distutils and twisted

Alexandre Fayolle alexandre.fayolle at free.fr
Fri Nov 8 06:16:49 EST 2002

On Wed, Nov 06, 2002 at 07:22:21PM +0100, Alexandre Fayolle wrote:
> IMNSHO, having a module
> twisted.python.distutils with a custom setup aware of tml files would be
> a nice thing to have for module developers (and I'm a bit surprised that
> no such beast exists). I'll hack something, and submit it to the mailing
> list if I'm happy enough with it.  

Well, here's an attempt. The documentation is in the module docstring.
Feel free to add it to the twisted distribution if you think it's ok.
If you need more features, please ask. If you find bugs, please tell me.

-------------- next part --------------
"""Distutils extensions for twisted framework.

This module enables the installation of plugins.tml files using standard
distutils syntax. It adds the following commands to the standard
setup.py commands:
* build_twisted_plugins: build (i.e. copy) plugins
* install_twisted_plugins: install plugins

Additionally, the following commands have been modified to deal with
plugins files:
 * sdist
 * build
 * install

To use these extenstion, you should import the setup fonction from this
module, and use it normally. To list the plugins.tml files, use the
twisted_plugins keyword argument to the setup function:

from twisted_distutils import setup # you can also import Extension if needed

if __name__ == '__main__':
          twisted_plugins = ['my_package/plugins.tml'])

Note that you can use this to install files that are not twisted plugins in any package directory of your application.
# (c) 2002 Alexandre Fayolle <alexandre.fayolle at free.fr>
# This module is heavily based on code copied from the python distutils
# framework, especially distutils.command.build_script,
# distutils.command.install_script. Many thanks to the authors of these
# modules.
# This module is provided as is, I'm not responsible if anything bad
# happens to you or your python library while using this module. You may
# freely copy it, distribute it and use it in your library or to distribute
# your applications. I'd appreciate if you could drop me an email if you plan
# to do so <wink>.
# Happy twisting!

from distutils.core import Extension,Distribution,Command
from distutils.command.install import install
from distutils.command.build import build
from distutils.command.sdist import sdist
from distutils.dep_util import newer
from distutils.util import convert_path
import os

class twisted_sdist(sdist):
    def add_defaults(self):
        if self.distribution.has_twisted_plugins():
            build_twisted_plugins = self.get_finalized_command('build_twisted_plugins')

class twisted_install(install):
    def initialize_options (self):
        self.twisted_plugins = None
    def has_twisted_plugins(self):
        print '$'*50,self.distribution.has_twisted_plugins()
        return self.distribution.has_twisted_plugins()
    sub_commands = []
    sub_commands.append(('install_twisted_plugins', has_twisted_plugins))

class twisted_build(build):
    def initialize_options (self):
        self.twisted_plugins = None
    def has_twisted_plugins(self):
        print '#'*50,self.distribution.has_twisted_plugins()
        return self.distribution.has_twisted_plugins()
    sub_commands = []
    sub_commands.append(('build_twisted_plugins', has_twisted_plugins))
    print '#'*50
    print sub_commands
    print '#'*50

class build_twisted_plugins (Command):

    description = "\"build\" twisted plugins (copy)"

    user_options = [
        ('build-dir=', 'd', "directory to \"build\" (copy) to"),
        ('force', 'f', "forcibly build everything (ignore file timestamps"),

    boolean_options = ['force']

    def initialize_options (self):
        self.build_dir = None
        self.twisted_plugins = None
        self.force = None
        self.outfiles = None

    def get_source_files(self):
        return self.twisted_plugins

    def finalize_options (self):
                                   ('build_lib', 'build_dir'),
                                   ('force', 'force'))
        self.twisted_plugins = self.distribution.twisted_plugins

    def run (self):
        if not self.twisted_plugins:

    def copy_twisted_plugins (self):
        """Copy each plugin listed in 'self.twisted_plugins'.
        for plugin in self.twisted_plugins:
            adjust = 0
            print '*'*80
            print plugin
            plugin = convert_path(plugin)
            print plugin
            print self.build_dir,os.path.basename(plugin)
            outfile = os.path.join(self.build_dir, plugin)
            print outfile
            print '*'*80
            if not self.force and not newer(plugin, outfile):
                self.announce("not copying %s (up-to-date)" % plugin)

            # Always open the file, but ignore failures in dry-run mode --
            # that way, we'll get accurate feedback if we can read the
            # plugin.
                f = open(plugin, "r")
            except IOError:
                if not self.dry_run:
                f = None
                self.copy_file(plugin, outfile)

class install_twisted_plugins(Command):

    description = "install twisted plugins"

    user_options = [
        ('install-dir=', 'd', "directory to install scripts to"),
        ('build-dir=','b', "build directory (where to install from)"),
        ('force', 'f', "force installation (overwrite existing files)"),
        ('skip-build', None, "skip the build steps"),

    boolean_options = ['force', 'skip-build']

    def initialize_options (self):
        self.install_dir = None
        self.force = 0
        self.build_dir = None
        self.skip_build = None

    def finalize_options (self):
        self.set_undefined_options('build', ('build_lib', 'build_dir'))
                                   ('install_lib', 'install_dir'),
                                   ('force', 'force'),
                                   ('skip_build', 'skip_build'),

    def run (self):
        if not self.skip_build:
        self.outfiles = self.copy_tree(self.build_dir, self.install_dir)

    def get_inputs (self):
        return self.distribution.twisted_plugins or []

    def get_outputs(self):
        return self.outfiles or []

class TwistedDistribution(Distribution):
    def __init__(self,attrs=None):
        self.twisted_plugins = None
        self.cmdclass = {'install':twisted_install,

    def has_twisted_plugins(self):
        return self.twisted_plugins and len(self.twisted_plugins) > 0

def setup(**attrs):
    from distutils.core import setup
    attrs['distclass'] = TwistedDistribution
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 241 bytes
Desc: not available
Url : http://twistedmatrix.com/pipermail/twisted-python/attachments/20021108/bc82ccca/attachment.pgp 

More information about the Twisted-Python mailing list