Source

setup-recipe / setup_recipe / __init__.py

import os, re, sys

class Recipe(object):
    """
    Buildout recipe that writes out script into bin directory. Script then runs `setup.py`
    in all configured directories using specified python interpreter.

    Supported options:
    * develop - List of directories, where `setup.py` file reside. Typically `${buildout:develop}` to list all developed apps.
    * use-interpreter - Name of python interpreter to use. Optional, when not specified, system interpreter is used.
    * command - Command line argument for the `setup.py` (or other defined script). Optional.
    * script - Name of the executed script. Defaults to `setup.py`.
    """

    def __init__(self, buildout, name, options):
        self.buildout, self.name, self.options = buildout, name, options

        self.develop = []
        for dir in re.split(r'\s+', self.options['develop']):
            if len(dir):
                self.develop.append(os.path.abspath(dir))

    def __escape(self, s):
        return s.replace('\\', '\\\\').replace('\n', ' ')

    def install(self):
        # Read settings
        bin = os.path.join(self.buildout['buildout']['directory'], 'bin')
        python = sys.executable
        output = os.path.join(bin, self.name)
        interpreter = os.path.join(bin, self.options.get('use-interpreter', python))
        command = self.options.get('command')
        script = self.options.get('script', 'setup.py')

        # Write out the script. Ugly but functional.
        f = open(output, 'w')
        f.write('#!' + python + '\n')

        f.write('import os, sys\n')
        f.write('from subprocess import call\n\n')

        # Write settings
        f.write('INTERPRETER = "' + self.__escape(interpreter) + '"\n')
        f.write('DEVELOP = ' + str(self.develop) + '\n')
        f.write('SCRIPT = "' + self.__escape(script) + '"\n')

        if command:
            f.write('CMD = ["' + self.__escape(command) + '"]\n')
        else:
            f.write('CMD = []\n')

        f.write('ARGS = sys.argv[1:]\n\n')

        # Loop that runs setup.py
        f.write('for dir in DEVELOP:\n')
        f.write('  print "Processing " + dir\n')
        f.write('  r = call([INTERPRETER, os.path.join(dir, SCRIPT)] + CMD + ARGS, cwd=dir)\n')
        f.write('  if r != 0:\n')
        f.write('    sys.exit(r)\n\n')

        # Finished
        f.write('print "All OK"\n')
        f.write('sys.exit(0)\n')

        f.close()

        # Make it executable
        os.chmod(output, 0755)

        return output

    update = install