from setuptools.command.easy_install import easy_install from distutils.util import convert_path from pkg_resources import Distribution, PathMetadata, normalize_path from distutils import log from distutils.errors import * import sys, os, setuptools, glob import virtualenv import textwrap import tempfile import subprocess import stat import pprint class Filler(object): TAB_WIDTH = 4 TAB_CHAR = ' ' LINE_LEN = 79 def __init__(self, indent): self._obj = None self.initial_indent = self.TAB_CHAR*self.TAB_WIDTH*indent indent+=1 self.subsequent_indent = self.TAB_CHAR*self.TAB_WIDTH*indent def __call__(self, text): text = text.rstrip() return self.process(text) @property def obj(self): if not self._obj: self._obj = textwrap.TextWrapper( width=self.LINE_LEN, initial_indent=self.initial_indent, subsequent_indent=self.subsequent_indent, ) return self._obj.fill def process(self, text): out = [] text = textwrap.dedent(text) obj = self.obj lines = text.split('\n') for line in lines: out.append(self.obj(line)) return '\n'.join(out) class AfterInstallActionBase(object): def _quote_list(self, data): if isinstance(data, basestring): out = ["'{0}'".format(data)] else: out = ["'{0}'".format(d) for d in data] return ', '.join(out) class EasyInstall(AfterInstallActionBase): CODE = """ for package in [{packages}]: easy_install(package) """ def __init__(self, packages): self.packages = self._quote_list(packages) self.fill = Filler(1) def __call__(self): code = self.CODE.format(packages=self.packages) return self.fill(code) class HgClone(AfterInstallActionBase): CODE = """ hg_clone('{url}', '{dest}') """ def __init__(self, url, dest): self.url = url self.dest = dest self.fill = Filler(1) def __call__(self): code = self.CODE.format(url=self.url, dest=self.dest) return self.fill(code) class RunSetupCommand(AfterInstallActionBase): CODE = """ for dir in [{dirs}]: setup_py(dir, {command}) """ def __init__(self, dirs, command): self.dirs = self._quote_list(dirs) self.command = repr(command).strip('[]()') self.fill = Filler(1) def __call__(self): code = self.CODE.format(dirs=self.dirs, command=self.command) return self.fill(code) class RunPythonPrograms(AfterInstallActionBase): CODE = """ for program in [{programs}]: run_program(program) """ def __init__(self, programs): self.programs = self._quote_list(programs) self.fill = Filler(1) def __call__(self): code = self.CODE.format(programs=self.programs) return self.fill(code) class AfterInstall(object): FILE = 'after_install.py' CODE = ''' def after_install(options, home_dir): paths = build_paths(home_dir) easy_install = EasyInstall(paths) hg_clone = HgClone(paths) setup_py = SetupPy(paths) run_program = RunPythonProgram(paths) ''' def __init__(self): self.fill = Filler(0) self._code_from_file_ = None @property def _code_from_file(self): if not self._code_from_file_: path = os.path.dirname(os.path.realpath(__file__)) path = os.path.join(path, self.FILE) fp = open(path, 'r') self._code_from_file_ = fp.read() fp.close() return self._code_from_file_ def __call__(self, chain): out = [self._code_from_file, self.fill(self.CODE)] for obj in chain: out.append(obj()) out = ''.join(out) return out class VirtualEnvDev(object): NAME = 'devstrap.py' PACKAGES = ['nose', 'virtualenv', 'ipython', 'mercurial', 'pylint'] HG_URL = 'hg clone https://dodai.googlecode.com/hg' HG_DEST = 'src' AFTER_BUILD = [] def __init__(self, path, name): self.name = '{0}-{1}'.format(name, self.NAME) self.path = os.path.join(path, self.name) def __call__(self): self._write() print "File Built: {0}".format(self.path) def _write(self): with open(self.path, 'w') as f: f.write(self._data) @property def _after_install(self): chain = [ EasyInstall(self.PACKAGES), HgClone(self.HG_URL, self.HG_DEST), RunSetupCommand(self.HG_DEST, 'develop'), RunPythonPrograms(self.AFTER_BUILD) ] obj = AfterInstall() return obj(chain) @property def _data(self): return virtualenv.create_bootstrap_script(self._after_install) class devstrap(easy_install): description = 'create a devstrap file used for installing a dev env' user_options = easy_install.user_options boolean_options = easy_install.boolean_options command_consumes_arguments = False def run(self): virtual_env = VirtualEnvDev(self.prefix, self.distribution.get_name()) virtual_env() def initialize_options(self): easy_install.initialize_options(self) def finalize_options(self): if self.prefix: if not os.path.exists(self.prefix): os.makedirs(self.prefix) else: self.prefix = os.getcwd()