diff options
| author | Jeremy Kloth <jeremy.kloth@gmail.com> | 2010-07-08 10:05:39 -0600 |
|---|---|---|
| committer | Jeremy Kloth <jeremy.kloth@gmail.com> | 2010-07-08 10:05:39 -0600 |
| commit | 0b2e95d77af6c5b8eb245e7a2aed3a34e186ad6d (patch) | |
| tree | b9d61b71e83e2486345b985c0f4a2a5d38fb94c1 /src/distutils2/command | |
| parent | e52f1bbc811ce8094e03e8cfccbd9a1d4c85980c (diff) | |
| parent | 480bbce9ae895702ac6f00d45e87e93ed8f2d4e5 (diff) | |
| download | disutils2-0b2e95d77af6c5b8eb245e7a2aed3a34e186ad6d.tar.gz | |
Merged with master repository
Diffstat (limited to 'src/distutils2/command')
| -rw-r--r-- | src/distutils2/command/bdist.py | 6 | ||||
| -rw-r--r-- | src/distutils2/command/bdist_dumb.py | 2 | ||||
| -rw-r--r-- | src/distutils2/command/bdist_msi.py | 4 | ||||
| -rw-r--r-- | src/distutils2/command/bdist_wininst.py | 4 | ||||
| -rw-r--r-- | src/distutils2/command/build_py.py | 75 | ||||
| -rw-r--r-- | src/distutils2/command/cmd.py | 11 | ||||
| -rw-r--r-- | src/distutils2/command/sdist.py | 2 | ||||
| -rw-r--r-- | src/distutils2/command/upload.py | 2 | ||||
| -rw-r--r-- | src/distutils2/command/upload_docs.py | 135 |
9 files changed, 216 insertions, 25 deletions
diff --git a/src/distutils2/command/bdist.py b/src/distutils2/command/bdist.py index 27f9ec3..147a31e 100644 --- a/src/distutils2/command/bdist.py +++ b/src/distutils2/command/bdist.py @@ -62,7 +62,7 @@ class bdist(Command): 'os2': 'zip'} # Establish the preferred order (for the --help-formats option). - format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar', + format_commands = ['gztar', 'bztar', 'ztar', 'tar', 'wininst', 'zip', 'msi'] # And the real information. @@ -96,7 +96,7 @@ class bdist(Command): # 'bdist_base' -- parent of per-built-distribution-format # temporary directories (eg. we'll probably have - # "build/bdist.<plat>/dumb", "build/bdist.<plat>/rpm", etc.) + # "build/bdist.<plat>/dumb", etc.) if self.bdist_base is None: build_base = self.get_finalized_command('build').build_base self.bdist_base = os.path.join(build_base, @@ -126,7 +126,7 @@ class bdist(Command): # Reinitialize and run each command. for i in range(len(self.formats)): cmd_name = commands[i] - sub_cmd = self.reinitialize_command(cmd_name) + sub_cmd = self.get_reinitialized_command(cmd_name) # passing the owner and group names for tar archiving if cmd_name == 'bdist_dumb': diff --git a/src/distutils2/command/bdist_dumb.py b/src/distutils2/command/bdist_dumb.py index 429725c..b36e7a3 100644 --- a/src/distutils2/command/bdist_dumb.py +++ b/src/distutils2/command/bdist_dumb.py @@ -85,7 +85,7 @@ class bdist_dumb (Command): if not self.skip_build: self.run_command('build') - install = self.reinitialize_command('install', reinit_subcommands=1) + install = self.get_reinitialized_command('install', reinit_subcommands=1) install.root = self.bdist_dir install.skip_build = self.skip_build install.warn_dir = 0 diff --git a/src/distutils2/command/bdist_msi.py b/src/distutils2/command/bdist_msi.py index 158065b..bbbcbcc 100644 --- a/src/distutils2/command/bdist_msi.py +++ b/src/distutils2/command/bdist_msi.py @@ -177,12 +177,12 @@ class bdist_msi (Command): if not self.skip_build: self.run_command('build') - install = self.reinitialize_command('install', reinit_subcommands=1) + install = self.get_reinitialized_command('install', reinit_subcommands=1) install.prefix = self.bdist_dir install.skip_build = self.skip_build install.warn_dir = 0 - install_lib = self.reinitialize_command('install_lib') + install_lib = self.get_reinitialized_command('install_lib') # we do not want to include pyc or pyo files install_lib.compile = 0 install_lib.optimize = 0 diff --git a/src/distutils2/command/bdist_wininst.py b/src/distutils2/command/bdist_wininst.py index 10f8bec..e0b93d1 100644 --- a/src/distutils2/command/bdist_wininst.py +++ b/src/distutils2/command/bdist_wininst.py @@ -126,13 +126,13 @@ class bdist_wininst (Command): if not self.skip_build: self.run_command('build') - install = self.reinitialize_command('install', reinit_subcommands=1) + install = self.get_reinitialized_command('install', reinit_subcommands=1) install.root = self.bdist_dir install.skip_build = self.skip_build install.warn_dir = 0 install.plat_name = self.plat_name - install_lib = self.reinitialize_command('install_lib') + install_lib = self.get_reinitialized_command('install_lib') # we do not want to include pyc or pyo files install_lib.compile = 0 install_lib.optimize = 0 diff --git a/src/distutils2/command/build_py.py b/src/distutils2/command/build_py.py index 7b0c70e..736c35e 100644 --- a/src/distutils2/command/build_py.py +++ b/src/distutils2/command/build_py.py @@ -6,14 +6,65 @@ __revision__ = "$Id: build_py.py 76956 2009-12-21 01:22:46Z tarek.ziade $" import os import sys +import logging from glob import glob from distutils2.core import Command from distutils2.errors import DistutilsOptionError, DistutilsFileError from distutils2.util import convert_path -from distutils2 import log - -class build_py(Command): +from distutils2.converter.refactor import DistutilsRefactoringTool + +# marking public APIs +__all__ = ['Mixin2to3', 'build_py'] + +try: + from distutils2.util import Mixin2to3 as _Mixin2to3 + from lib2to3.refactor import get_fixers_from_package + _CONVERT = True + _KLASS = _Mixin2to3 +except ImportError: + _CONVERT = False + _KLASS = object + +class Mixin2to3(_KLASS): + """ The base class which can be used for refactoring. When run under + Python 3.0, the run_2to3 method provided by Mixin2to3 is overridden. + When run on Python 2.x, it merely creates a class which overrides run_2to3, + yet does nothing in particular with it. + """ + if _CONVERT: + def _run_2to3(self, files, doctests=[]): + """ Takes a list of files and doctests, and performs conversion + on those. + - First, the files which contain the code(`files`) are converted. + - Second, the doctests in `files` are converted. + - Thirdly, the doctests in `doctests` are converted. + """ + + # Convert the ".py" files. + logging.info("Converting Python code") + _KLASS.run_2to3(self, files) + + # Convert the doctests in the ".py" files. + logging.info("Converting doctests with '.py' files") + _KLASS.run_2to3(self, files, doctests_only=True) + + # If the following conditions are met, then convert:- + # 1. User has specified the 'convert_2to3_doctests' option. So, we + # can expect that the list 'doctests' is not empty. + # 2. The default is allow distutils2 to allow conversion of text files + # containing doctests. It is set as + # distutils2.run_2to3_on_doctests + + if doctests != [] and distutils2.run_2to3_on_doctests: + logging.info("Converting text files which contain doctests") + _KLASS.run_2to3(self, doctests, doctests_only=True) + else: + # If run on Python 2.x, there is nothing to do. + def _run_2to3(self, files, doctests=[]): + pass + +class build_py(Command, Mixin2to3): description = "\"build\" pure Python modules (copy to build directory)" @@ -39,6 +90,8 @@ class build_py(Command): self.compile = 0 self.optimize = 0 self.force = None + self._updated_files = [] + self._doctests_2to3 = [] def finalize_options(self): self.set_undefined_options('build', @@ -93,6 +146,9 @@ class build_py(Command): self.build_packages() self.build_package_data() + if self.distribution.use_2to3 and self_updated_files: + self.run_2to3(self._updated_files, self._doctests_2to3) + self.byte_compile(self.get_outputs(include_bytecode=0)) # -- Top-level worker functions ------------------------------------ @@ -148,8 +204,10 @@ class build_py(Command): for filename in filenames: target = os.path.join(build_dir, filename) self.mkpath(os.path.dirname(target)) - self.copy_file(os.path.join(src_dir, filename), target, - preserve_mode=False) + outf, copied = self.copy_file(os.path.join(src_dir, filename), + target, preserve_mode=False) + if copied and srcfile in self.distribution.convert_2to3.doctests: + self._doctests_2to3.append(outf) # XXX - this should be moved to the Distribution class as it is not # only needed for build_py. It also has no dependencies on this class. @@ -215,8 +273,8 @@ class build_py(Command): if os.path.isfile(init_py): return init_py else: - log.warn(("package init file '%s' not found " + - "(or not a regular file)"), init_py) + logging.warning(("package init file '%s' not found " + + "(or not a regular file)"), init_py) # Either not in a package at all (__init__.py not expected), or # __init__.py doesn't exist -- so don't return the filename. @@ -224,7 +282,8 @@ class build_py(Command): def check_module(self, module, module_file): if not os.path.isfile(module_file): - log.warn("file %s (for module %s) not found", module_file, module) + logging.warning("file %s (for module %s) not found", + module_file, module) return False else: return True diff --git a/src/distutils2/command/cmd.py b/src/distutils2/command/cmd.py index 161fc46..502bbfd 100644 --- a/src/distutils2/command/cmd.py +++ b/src/distutils2/command/cmd.py @@ -19,7 +19,7 @@ try: except ImportError: from distutils2._backport.shutil import make_archive -class Command: +class Command(object): """Abstract base class for defining command classes, the "worker bees" of the Distutils. A useful analogy for command classes is to think of them as subroutines with local variables called "options". The options @@ -57,8 +57,7 @@ class Command: def __init__(self, dist): """Create and initialize a new Command object. Most importantly, invokes the 'initialize_options()' method, which is the real - initializer and depends on the actual command being - instantiated. + initializer and depends on the actual command being instantiated. """ # late import because of mutual dependence between these classes from distutils2.dist import Distribution @@ -333,10 +332,8 @@ class Command: cmd_obj.ensure_finalized() return cmd_obj - # XXX rename to 'get_reinitialized_command()'? (should do the - # same in dist.py, if so) - def reinitialize_command(self, command, reinit_subcommands=0): - return self.distribution.reinitialize_command( + def get_reinitialized_command(self, command, reinit_subcommands=0): + return self.distribution.get_reinitialized_command( command, reinit_subcommands) def run_command(self, command): diff --git a/src/distutils2/command/sdist.py b/src/distutils2/command/sdist.py index bb4cd1f..f893aa1 100644 --- a/src/distutils2/command/sdist.py +++ b/src/distutils2/command/sdist.py @@ -20,7 +20,7 @@ except ImportError: from distutils2.core import Command from distutils2 import util from distutils2.errors import (DistutilsPlatformError, DistutilsOptionError, - DistutilsTemplateError) + DistutilsTemplateError) from distutils2.manifest import Manifest from distutils2 import log from distutils2.util import convert_path, newer diff --git a/src/distutils2/command/upload.py b/src/distutils2/command/upload.py index fb925ee..14fe119 100644 --- a/src/distutils2/command/upload.py +++ b/src/distutils2/command/upload.py @@ -160,7 +160,7 @@ class upload(PyPIRCCommand): # send the data try: result = urlopen(request) - status = result.getcode() + status = result.code reason = result.msg except socket.error, e: self.announce(str(e), log.ERROR) diff --git a/src/distutils2/command/upload_docs.py b/src/distutils2/command/upload_docs.py new file mode 100644 index 0000000..8e76776 --- /dev/null +++ b/src/distutils2/command/upload_docs.py @@ -0,0 +1,135 @@ +import base64, httplib, os.path, socket, tempfile, urlparse, zipfile +from cStringIO import StringIO +from distutils2 import log +from distutils2.command.upload import upload +from distutils2.core import PyPIRCCommand +from distutils2.errors import DistutilsFileError + +def zip_dir(directory): + """Compresses recursively contents of directory into a StringIO object""" + destination = StringIO() + zip_file = zipfile.ZipFile(destination, "w") + for root, dirs, files in os.walk(directory): + for name in files: + full = os.path.join(root, name) + relative = root[len(directory):].lstrip(os.path.sep) + dest = os.path.join(relative, name) + zip_file.write(full, dest) + zip_file.close() + return destination + +# grabbed from +# http://code.activestate.com/recipes/146306-http-client-to-post-using-multipartform-data/ +def encode_multipart(fields, files, boundary=None): + """ + fields is a sequence of (name, value) elements for regular form fields. + files is a sequence of (name, filename, value) elements for data to be uploaded as files + Return (content_type, body) ready for httplib.HTTP instance + """ + if boundary is None: + boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' + l = [] + for (key, value) in fields: + l.extend([ + '--' + boundary, + 'Content-Disposition: form-data; name="%s"' % key, + '', + value]) + for (key, filename, value) in files: + l.extend([ + '--' + boundary, + 'Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename), + '', + value]) + l.append('--' + boundary + '--') + l.append('') + body = '\r\n'.join(l) + content_type = 'multipart/form-data; boundary=%s' % boundary + return content_type, body + +class upload_docs(PyPIRCCommand): + + user_options = [ + ('repository=', 'r', "url of repository [default: %s]" % upload.DEFAULT_REPOSITORY), + ('show-response', None, 'display full response text from server'), + ('upload-dir=', None, 'directory to upload'), + ] + + def initialize_options(self): + PyPIRCCommand.initialize_options(self) + self.upload_dir = "build/docs" + + def finalize_options(self): + PyPIRCCommand.finalize_options(self) + if self.upload_dir == None: + build = self.get_finalized_command('build') + self.upload_dir = os.path.join(build.build_base, "docs") + self.announce('Using upload directory %s' % self.upload_dir) + self.verify_upload_dir(self.upload_dir) + config = self._read_pypirc() + if config != {}: + self.username = config['username'] + self.password = config['password'] + self.repository = config['repository'] + self.realm = config['realm'] + + def verify_upload_dir(self, upload_dir): + self.ensure_dirname('upload_dir') + index_location = os.path.join(upload_dir, "index.html") + if not os.path.exists(index_location): + mesg = "No 'index.html found in docs directory (%s)" + raise DistutilsFileError(mesg % upload_dir) + + def run(self): + tmp_dir = tempfile.mkdtemp() + name = self.distribution.metadata['Name'] + zip_file = zip_dir(self.upload_dir) + + fields = {':action': 'doc_upload', 'name': name}.items() + files = [('content', name, zip_file.getvalue())] + content_type, body = encode_multipart(fields, files) + + credentials = self.username + ':' + self.password + auth = "Basic " + base64.encodestring(credentials).strip() + + self.announce("Submitting documentation to %s" % (self.repository), + log.INFO) + + schema, netloc, url, params, query, fragments = \ + urlparse.urlparse(self.repository) + if schema == "http": + conn = httplib.HTTPConnection(netloc) + elif schema == "https": + conn = httplib.HTTPSConnection(netloc) + else: + raise AssertionError("unsupported schema "+schema) + + try: + conn.connect() + conn.putrequest("POST", url) + conn.putheader('Content-type', content_type) + conn.putheader('Content-length', str(len(body))) + conn.putheader('Authorization', auth) + conn.endheaders() + conn.send(body) + except socket.error, e: + self.announce(str(e), log.ERROR) + return + + r = conn.getresponse() + + if r.status == 200: + self.announce('Server response (%s): %s' % (r.status, r.reason), + log.INFO) + elif r.status == 301: + location = r.getheader('Location') + if location is None: + location = 'http://packages.python.org/%s/' % meta.get_name() + self.announce('Upload successful. Visit %s' % location, + log.INFO) + else: + self.announce('Upload failed (%s): %s' % (r.status, r.reason), + log.ERROR) + + if self.show_response: + print "\n".join(['-'*75, r.read(), '-'*75]) |
