[Zope-CVS] CVS: Packages/zpkgtools/zpkgtools - app.py:1.1

Fred L. Drake, Jr. fred at zope.com
Wed Mar 31 11:30:47 EST 2004


Update of /cvs-repository/Packages/zpkgtools/zpkgtools
In directory cvs.zope.org:/tmp/cvs-serv15676/zpkgtools

Added Files:
	app.py 
Log Message:
move most of the application code out of the top-level script and into a
module; this will make it easier to write tests


=== Added File Packages/zpkgtools/zpkgtools/app.py ===
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################

import logging
import optparse
import os
import shutil
import sys
import tempfile

import zpkgtools

from zpkgtools import config
from zpkgtools import cvsloader
from zpkgtools import include
from zpkgtools import locationmap
from zpkgtools import package
from zpkgtools import publication


class Application:

    def __init__(self, options, resource, program):
        self.logger = logging.getLogger(program)
        self.ip = None
        self.options = options
        self.resource = locationmap.normalizeResourceId(resource)
        self.resource_type, self.resource_name = self.resource.split(":", 1)
        # Create a new directory for all temporary files to go in:
        self.tmpdir = tempfile.mkdtemp(prefix=program + "-")
        tempfile.tempdir = self.tmpdir
        self.loader = cvsloader.CvsLoader()
        cf = config.Configuration()
        path = options.configfile
        if path is None:
            path = config.defaultConfigurationPath()
            if os.path.exists(path):
                cf.loadPath(path)
        elif path:
            cf.loadPath(path)

        if options.location_maps:
            cf.location_maps[:0] = options.location_maps
        cf.finalize()
        self.locations = cf.locations
        if options.include_support_code is None:
            options.include_support_code = cf.include_support_code

        if resource not in self.locations:
            print >>sys.stderr, "unknown resource:", resource
            sys.exit(1)
        self.resource_url = self.locations[resource]

    def buildDistribution(self):
        # This could be either a package distribution or a collection
        # distribution; it's the former if there's an __init__.py in
        # the source directory.
        name = "build%sDistribution" % self.resource_type.capitalize()
        method = getattr(self, name)
        method()
        self.generateSetup()

    def buildPackageDistribution(self):
        os.mkdir(self.destination)
        pkgname = self.metadata.name

        self.ip = include.InclusionProcessor(
            self.source, os.path.join(self.destination, pkgname))
        # XXX Ouch!  Need a better way to deal with this.  The
        # InclusionProcessor API doesn't smell right.
        self.ip.manifest_prefix = os.path.join(self.destination, "")
        try:
            self.ip.createDistributionTree()
        except cvsloader.CvsLoadingError, e:
            print >>sys.stderr, e
            sys.exit(1)
        pkgdir = os.path.join(self.destination, pkgname)
        pkginfo = package.loadPackageInfo(pkgname, pkgdir, pkgname)
        if pkginfo.documentation:
            setup_cfg = os.path.join(self.destination, "setup.cfg")
            self.ip.add_output(setup_cfg)
            prefix = "doc_files = "
            s = "\n" + (" " * len(prefix))
            f = open(setup_cfg, "w")
            f.write("[bdist_rpm]\n")
            f.write(prefix)
            f.write(s.join(pkginfo.documentation))
            f.write("\n")
            f.close()

    def buildCollectionDistribution(self):
        # Build the destination directory:
        self.ip = include.InclusionProcessor(self.source,
                                             self.destination)
        try:
            self.ip.createDistributionTree()
        except cvsloader.CvsLoadingError, e:
            print >>sys.stderr, e
            sys.exit(1)
        deps_file = os.path.join(self.source, "DEPENDENCIES.txt")
        if os.path.isfile(deps_file):
            for dep in dependencies.load(open(deps_file)):
                if dep in self.locations:
                    # we can get this
                    pass
                else:
                    # external dependency
                    pass

    def loadMetadata(self):
        metadata_file = os.path.join(self.source, "PUBLICATION.txt")
        if not os.path.isfile(metadata_file):
            print >>sys.stderr, \
                  "source-dir does not contain required publication data file"
            sys.exit(1)
        self.metadata = publication.load(open(metadata_file))

    def loadResource(self):
        self.source = self.loader.load(self.resource_url)
        self.loadMetadata()
        if not self.options.release_name:
            self.options.release_name = self.metadata.name.replace(" ", "-")
        release_name = self.options.release_name
        self.target_name = "%s-%s" % (release_name, self.options.version)
        self.target_file = self.target_name + ".tar.bz2"
        self.destination = os.path.join(self.tmpdir, self.target_name)

    def generateSetup(self):
        setup_py = os.path.join(self.destination, "setup.py")
        self.ip.add_output(setup_py)
        pkgname = self.resource_name
        type = self.resource_type
        f = open(setup_py, "w")
        print >>f, SETUP_HEADER
        print >>f, "context = zpkgtools.setup.%sContext(" % type.capitalize()
        print >>f, "    %r, %r, __file__)" % (pkgname, self.options.version)
        print >>f
        print >>f, "context.setup()"
        f.close()

    def includeSupportCode(self):
        zpkgtools_dest = os.path.join(self.destination, "zpkgtools")
        # Since we might actually be including zpkgtools as an
        # installable package, we only do this if we need to:
        if not os.path.exists(zpkgtools_dest):
            self.ip.copyTree(zpkgtools.__path__[0], zpkgtools_dest)
            tests_dir = os.path.join(zpkgtools_dest, "tests")
            # XXX We could toss the tests, but that would screw up the
            # manifest, so we'll leave them in for now.
        # now we need to find setuptools:
        setuptools_dest = os.path.join(self.destination, "setuptools")
        if os.path.exists(setuptools_dest):
            # already have it
            return
        source = None
        if "setuptools" in self.locations:
            url = self.locations["setuptools"]
        else:
            try:
                import setuptools
            except ImportError:
                # last resort
                url = ("cvs://cvs.python.sourceforge.net/cvsroot/python"
                       ":python/nondist/sandbox/setuptools/setuptools")
                self.logger.info("resource package:setuptools not configured;"
                                 " using bootstrap URL")
            else:
                source = os.path.abspath(setuptools.__path__[0])
        if source is None:
            source = self.loader.load(url)

        self.ip.copyTree(source, setuptools_dest)
        tests_dir = os.path.join(setuptools_dest, "tests")
        # XXX We could toss the tests, but that would screw up the
        # manifest, so we'll leave them in for now.

    def createManifest(self):
        if self.ip is None:
            return
        manifest_path = os.path.join(self.destination, "MANIFEST")
        f = file(manifest_path, "w")
        for name in self.ip.manifest:
            print >>f, name
        f.close()

    def createTarball(self):
        pwd = os.getcwd()
        os.chdir(self.tmpdir)
        try:
            rc = os.spawnlp(os.P_WAIT, "tar",
                            "tar", "cjf", self.target_file, self.target_name)
        finally:
            os.chdir(pwd)
        if rc:
            print >>sys.stderr, "error generating", self.target_file
            sys.exit(1)
        # We have a tarball; clear some space, then copy the tarball
        # to the current directory:
        shutil.rmtree(self.destination)
        shutil.copy(os.path.join(self.tmpdir, self.target_file),
                    self.target_file)

    def cleanup(self):
        shutil.rmtree(self.tmpdir)

    def run(self):
        try:
            try:
                self.loadResource()
                self.buildDistribution()
                if self.options.include_support_code:
                    self.includeSupportCode()
            except cvsloader.CvsLoadingError, e:
                print >>sys.stderr, e
                sys.exit(e.exitcode)
            self.createManifest()
            self.createTarball()
            self.cleanup()
        except:
            print >>sys.stderr, "temporary files are in", self.tmpdir
            raise


SETUP_HEADER = """\
#! /usr/bin/env python
#
# THIS IS A GENERATED FILE.  DO NOT EDIT THIS DIRECTLY.

import zpkgtools.setup

"""


def main(argv=None):
    if argv is None:
        argv = sys.argv
    program = os.path.basename(argv[0])
    parser = optparse.OptionParser(
        usage="usage: %prog [options] resource",
        version="%prog 0.1")
    parser.add_option(
        "-C", "--configure", dest="configfile",
        help="path or URL to the configuration file", metavar="FILE")
    parser.add_option(
        "-f", dest="configfile",
        action="store_const", const="",
        help="don't read a configuration file")
    parser.add_option(
        "-m", "--resource-map", dest="location_maps",
        action="append",
        help=("specify an additional location map to load before"
              " maps specified in the configuration"), metavar="MAP")
    parser.add_option(
        "-n", "--name", dest="release_name",
        help="base name of the distribution file", metavar="NAME")
    parser.add_option(
        "-r", "--revision-tag", dest="revision_tag",
        help="default CVS tag to use (default: HEAD)", metavar="TAG",
        default="HEAD")
    parser.add_option(
        "-S", dest="include_support_code", action="store_false",
        help="don't include copies of the zpkgtools support code")
    parser.add_option(
        "-s", dest="include_support_code", action="store_true",
        help="include copies of the zpkgtools support code (the default)")
    parser.add_option(
        "-v", dest="version",
        help="version label for the new distribution",
        default="0.0.0")
    options, args = parser.parse_args(argv[1:])

    # figure out what to read from:
    if len(args) != 1:
        print >>sys.stderr, "wrong number of arguments"
        return 2
    resource = args[0]

    try:
        app = Application(options, resource, program)
        app.run()
    except SystemExit, e:
        return e.code
    except KeyboardInterrupt:
        return 1
    else:
        return 0




More information about the Zope-CVS mailing list