316 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			316 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Python
		
	
	
	
import sys
 | 
						|
 | 
						|
sys.path.insert(0, sys.argv[1])
 | 
						|
import py
 | 
						|
 | 
						|
toolpath = py.path.local(__file__)
 | 
						|
binpath = py.path.local(py.__file__).dirpath('bin')
 | 
						|
 | 
						|
def error(msg):
 | 
						|
    print >>sys.stderr, msg
 | 
						|
    raise SystemExit, 1
 | 
						|
 | 
						|
def reformat(text):
 | 
						|
    return " ".join(text.split())
 | 
						|
 | 
						|
class SetupWriter(object):
 | 
						|
    EXCLUDES = ("MANIFEST.in", "contrib")
 | 
						|
 | 
						|
    def __init__(self, basedir, pkg, setuptools=False):
 | 
						|
        self.basedir = basedir
 | 
						|
        self.setuptools = setuptools
 | 
						|
        assert self.basedir.check()
 | 
						|
        self.pkg = pkg
 | 
						|
        self.meta = pkg.__pkg__
 | 
						|
        self.lines = []
 | 
						|
        self.allpaths = self.getallpath(self.basedir)
 | 
						|
 | 
						|
    def getallpath(self, basedir):
 | 
						|
        contrib = self.basedir.join("contrib")
 | 
						|
        allpath = []
 | 
						|
        lines = py.process.cmdexec("hg st -mcan").split("\n")
 | 
						|
        for path in lines:
 | 
						|
            p = basedir.join(path)
 | 
						|
            assert p.check(), p
 | 
						|
            if not p.relto(contrib) and p != contrib and not self.isexcluded(p):
 | 
						|
                allpath.append(p)
 | 
						|
        return allpath
 | 
						|
 | 
						|
    def append(self, string):
 | 
						|
        lines = string.split("\n")
 | 
						|
        while lines:
 | 
						|
            if not lines[0].strip():
 | 
						|
                lines.pop(0)
 | 
						|
                continue
 | 
						|
            break
 | 
						|
        if not lines:
 | 
						|
            self.lines.append("")
 | 
						|
            return
 | 
						|
        line = lines[0]
 | 
						|
        indent = len(line) - len(line.lstrip())
 | 
						|
        for line in lines:
 | 
						|
            if line.strip():
 | 
						|
                assert not line[:indent].strip(), line
 | 
						|
                line = line[indent:]
 | 
						|
            self.lines.append(line)
 | 
						|
 | 
						|
    def write_winfuncs(self):
 | 
						|
        self.append('''
 | 
						|
        ''')
 | 
						|
 | 
						|
    def tip_info(self, indent=8):
 | 
						|
        old = self.basedir.chdir()
 | 
						|
        indent = " " * indent
 | 
						|
        try:
 | 
						|
            info = []
 | 
						|
            output = py.process.cmdexec(
 | 
						|
                "hg tip --template '" # tags: {tags}\n"
 | 
						|
                #"branch: {branches}\n"
 | 
						|
                "revision: {rev}:{node}\n'"
 | 
						|
            )
 | 
						|
            for line in output.split("\n"):
 | 
						|
                info.append("%s %s" %(indent, line.strip()))
 | 
						|
            return "\n".join(info)
 | 
						|
        finally:
 | 
						|
            old.chdir()
 | 
						|
 | 
						|
    def setup_header(self):
 | 
						|
        #tooltime = "%s %s" %(py.std.time.asctime(), py.std.time.tzname[0])
 | 
						|
        toolname = toolpath.basename
 | 
						|
        #toolrevision = py.path.svnwc(toolpath).info().rev
 | 
						|
 | 
						|
        pkgname = self.pkg.__name__
 | 
						|
        self.append('"""py lib / py.test setup.py file"""')
 | 
						|
        self.append('import os, sys')
 | 
						|
        self.append("from setuptools import setup")
 | 
						|
 | 
						|
    def setup_trailer(self):
 | 
						|
        self.append('''
 | 
						|
            if __name__ == '__main__':
 | 
						|
                main()
 | 
						|
        ''')
 | 
						|
 | 
						|
    def setup_function(self):
 | 
						|
        params = self.__dict__.copy()
 | 
						|
        params.update(self.meta.__dict__)
 | 
						|
        self.append('long_description = """')
 | 
						|
        for line in params['long_description'].split('\n'):
 | 
						|
            self.append(line)
 | 
						|
        self.append('"""')
 | 
						|
        trunk = None
 | 
						|
        if params['version'] == 'trunk':
 | 
						|
            trunk = 'trunk'
 | 
						|
        self.append('trunk = %r' % trunk)
 | 
						|
        self.append('''
 | 
						|
            def main():
 | 
						|
                setup(
 | 
						|
                    name=%(name)r,
 | 
						|
                    description=%(description)r,
 | 
						|
                    long_description = long_description,
 | 
						|
                    version= trunk or %(version)r,
 | 
						|
                    url=%(url)r,
 | 
						|
                    license=%(license)r,
 | 
						|
                    platforms=%(platforms)r,
 | 
						|
                    author=%(author)r,
 | 
						|
                    author_email=%(author_email)r,
 | 
						|
        ''' % params)
 | 
						|
        indent = " " * 8
 | 
						|
        self.append_pprint(indent, entry_points={'console_scripts':self.getconsolescripts()})
 | 
						|
        self.append_pprint(indent, classifiers=self.meta.classifiers)
 | 
						|
        self.append_pprint(indent, packages=self.getpackages())
 | 
						|
        self.append_pprint(indent, package_data=self.getpackagedata())
 | 
						|
        self.append_pprint(indent, zip_safe=True)
 | 
						|
        self.append_pprint(indent, install_requires=['apipkg'])
 | 
						|
        self.lines.append(indent[4:] + ")\n")
 | 
						|
 | 
						|
    def setup_scripts(self):
 | 
						|
        # XXX this was used for a different approach
 | 
						|
        not used
 | 
						|
        self.append("""
 | 
						|
            def getscripts():
 | 
						|
                if sys.platform == "win32":
 | 
						|
                    base = "py/bin/win32/"
 | 
						|
                    ext = ".cmd"
 | 
						|
                else:
 | 
						|
                    base = "py/bin/"
 | 
						|
                    ext = ""
 | 
						|
                l = []
 | 
						|
                for name in %r:
 | 
						|
                    l.append(base + name + ext)
 | 
						|
                return l
 | 
						|
        """ % ([script.basename for script in binpath.listdir("py.*")]))
 | 
						|
 | 
						|
    def append_pprint(self, indent, append=",", **kw):
 | 
						|
        for name, value in kw.items():
 | 
						|
            stringio = py.std.StringIO.StringIO()
 | 
						|
            value = py.std.pprint.pprint(value, stream=stringio)
 | 
						|
            stringio.seek(0)
 | 
						|
            lines =  stringio.readlines()
 | 
						|
            line = lines.pop(0).rstrip()
 | 
						|
            self.lines.append(indent + "%s=%s" %(name, line))
 | 
						|
            indent = indent + " " * (len(name)+1)
 | 
						|
            for line in lines:
 | 
						|
                self.lines.append(indent + line.rstrip())
 | 
						|
            self.lines[-1] = self.lines[-1] + append
 | 
						|
 | 
						|
    def getconsolescripts(self):
 | 
						|
        bindir = self.basedir.join('py', 'bin')
 | 
						|
        scripts = []
 | 
						|
        for p in self.allpaths:
 | 
						|
            if p.dirpath() == bindir:
 | 
						|
                if p.basename.startswith('py.'):
 | 
						|
                    shortname = "py" + p.basename[3:]
 | 
						|
                    scripts.append("%s = py.cmdline:%s" %
 | 
						|
                        (p.basename, shortname))
 | 
						|
        return scripts
 | 
						|
 | 
						|
    def getscripts(self):
 | 
						|
        bindir = self.basedir.join('py', 'bin')
 | 
						|
        scripts = []
 | 
						|
        for p in self.allpaths:
 | 
						|
            if p.dirpath() == bindir:
 | 
						|
                if p.basename.startswith('py.'):
 | 
						|
                    scripts.append(p.relto(self.basedir))
 | 
						|
        return scripts
 | 
						|
 | 
						|
    def getpackages(self):
 | 
						|
        packages = []
 | 
						|
        for p in self.allpaths: # contains no directories!
 | 
						|
            #if p.basename == "py":
 | 
						|
            #    continue
 | 
						|
            if p.dirpath('__init__.py').check():
 | 
						|
                modpath = p.dirpath().relto(self.basedir).replace(p.sep, '.')
 | 
						|
                if modpath != "py" and not modpath.startswith("py."):
 | 
						|
                    continue
 | 
						|
                if modpath in packages:
 | 
						|
                    continue
 | 
						|
                for exclude in self.EXCLUDES:
 | 
						|
                    if modpath.startswith(exclude):
 | 
						|
                        print "EXCLUDING", modpath
 | 
						|
                        break
 | 
						|
                else:
 | 
						|
                    packages.append(modpath)
 | 
						|
        packages.sort()
 | 
						|
        return packages
 | 
						|
 | 
						|
    def getpackagedata(self):
 | 
						|
        datafiles = []
 | 
						|
        pkgbase = self.basedir.join(self.pkg.__name__)
 | 
						|
        for p in self.allpaths:
 | 
						|
            if p.check(file=1) and (not p.dirpath("__init__.py").check()
 | 
						|
               or p.ext != ".py"):
 | 
						|
                if p.dirpath() != self.basedir:
 | 
						|
                    x = p.relto(pkgbase)
 | 
						|
                    if x:
 | 
						|
                        datafiles.append(p.relto(pkgbase))
 | 
						|
        return {'py': datafiles}
 | 
						|
 | 
						|
    def getdatafiles(self):
 | 
						|
        datafiles = []
 | 
						|
        for p in self.allpaths:
 | 
						|
            if p.check(file=1) and not p.ext == ".py":
 | 
						|
                if p.dirpath() != self.basedir:
 | 
						|
                    datafiles.append(p.relto(self.basedir))
 | 
						|
        return datafiles
 | 
						|
 | 
						|
    def setup_win32(self):
 | 
						|
        import winpath
 | 
						|
        self.append(py.std.inspect.getsource(winpath))
 | 
						|
        self.append("""
 | 
						|
            from distutils.command.install import install
 | 
						|
            class my_install(install):
 | 
						|
                def finalize_other(self):
 | 
						|
                    install.finalize_other(self)
 | 
						|
                    on_win32_add_to_PATH()
 | 
						|
            cmdclass = {'install': my_install}
 | 
						|
        """)
 | 
						|
 | 
						|
    def setup_win32(self):
 | 
						|
        self.append(r'''
 | 
						|
        # scripts for windows: turn "py.SCRIPT" into "py_SCRIPT" and create
 | 
						|
        # "py.SCRIPT.cmd" files invoking "py_SCRIPT"
 | 
						|
        from distutils.command.install_scripts import install_scripts
 | 
						|
        class my_install_scripts(install_scripts):
 | 
						|
            def run(self):
 | 
						|
                install_scripts.run(self)
 | 
						|
                #print self.outfiles
 | 
						|
                for fn in self.outfiles:
 | 
						|
                    basename = os.path.basename(fn)
 | 
						|
                    if basename.startswith("py.") and not basename.endswith(".cmd"):
 | 
						|
                        newbasename = basename.replace(".", "_")
 | 
						|
                        newfn = os.path.join(os.path.dirname(fn), newbasename)
 | 
						|
                        if os.path.exists(newfn):
 | 
						|
                            os.remove(newfn)
 | 
						|
                        os.rename(fn, newfn)
 | 
						|
                        fncmd = fn + ".cmd"
 | 
						|
                        if os.path.exists(fncmd):
 | 
						|
                           os.remove(fncmd)
 | 
						|
                        f = open(fncmd, 'w')
 | 
						|
                        f.write("@echo off\n")
 | 
						|
                        f.write('python "%%~dp0\%s" %%*' %(newbasename))
 | 
						|
                        f.close()
 | 
						|
        if sys.platform == "win32":
 | 
						|
            cmdclass = {'install_scripts': my_install_scripts}
 | 
						|
        else:
 | 
						|
            cmdclass = {}
 | 
						|
        ''')
 | 
						|
 | 
						|
    def write_setup(self):
 | 
						|
        self.setup_header()
 | 
						|
        self.setup_function()
 | 
						|
        #self.setup_scripts()
 | 
						|
        #self.setup_win32()
 | 
						|
        self.setup_trailer()
 | 
						|
        targetfile = self.basedir.join("setup.py")
 | 
						|
        targetfile.write("\n".join(self.lines))
 | 
						|
        print "wrote",  targetfile
 | 
						|
 | 
						|
    def isexcluded(self, wcpath):
 | 
						|
        return wcpath.basename[0] == "."
 | 
						|
        rel = wcpath.relto(self.basedir)
 | 
						|
        if rel.find("testing") != -1:
 | 
						|
            return True
 | 
						|
 | 
						|
    def write_manifest(self):
 | 
						|
        lines = []
 | 
						|
        for p in self.allpaths:
 | 
						|
            if p.check(dir=1):
 | 
						|
                continue
 | 
						|
            toadd = p.relto(self.basedir)
 | 
						|
            if toadd:
 | 
						|
                for exclude in self.EXCLUDES:
 | 
						|
                    if toadd.startswith(exclude):
 | 
						|
                        break
 | 
						|
                    assert toadd.find(exclude) == -1, (toadd, exclude)
 | 
						|
                else:
 | 
						|
                    lines.append("%s" %(toadd))
 | 
						|
        lines.sort()
 | 
						|
        targetfile = self.basedir.join("MANIFEST")
 | 
						|
        targetfile.write("\n".join(lines))
 | 
						|
        print "wrote",  targetfile
 | 
						|
 | 
						|
    def write_all(self):
 | 
						|
        #self.write_manifest()
 | 
						|
        self.write_setup()
 | 
						|
 | 
						|
def parseargs():
 | 
						|
    basedir = py.path.local(sys.argv[1])
 | 
						|
    if not basedir.check():
 | 
						|
        error("basedir not found: %s" %(basedir,))
 | 
						|
    pydir = basedir.join('py')
 | 
						|
    if not pydir.check():
 | 
						|
        error("no 'py' directory found in: %s" %(pydir,))
 | 
						|
    actualpydir = py.path.local(py.__file__).dirpath()
 | 
						|
    if pydir != actualpydir:
 | 
						|
        error("package dir conflict, %s != %s" %(pydir, actualpydir))
 | 
						|
    return basedir
 | 
						|
 | 
						|
def main(basedir=None):
 | 
						|
    if basedir is None:
 | 
						|
        basedir = parseargs()
 | 
						|
    writer = SetupWriter(basedir, py, setuptools=True)
 | 
						|
    writer.write_all()
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    main()
 |