summaryrefslogtreecommitdiff
path: root/src/distutils2/command
diff options
context:
space:
mode:
authorJeremy Kloth <jeremy.kloth@gmail.com>2010-07-08 10:05:39 -0600
committerJeremy Kloth <jeremy.kloth@gmail.com>2010-07-08 10:05:39 -0600
commit0b2e95d77af6c5b8eb245e7a2aed3a34e186ad6d (patch)
treeb9d61b71e83e2486345b985c0f4a2a5d38fb94c1 /src/distutils2/command
parente52f1bbc811ce8094e03e8cfccbd9a1d4c85980c (diff)
parent480bbce9ae895702ac6f00d45e87e93ed8f2d4e5 (diff)
downloaddisutils2-0b2e95d77af6c5b8eb245e7a2aed3a34e186ad6d.tar.gz
Merged with master repository
Diffstat (limited to 'src/distutils2/command')
-rw-r--r--src/distutils2/command/bdist.py6
-rw-r--r--src/distutils2/command/bdist_dumb.py2
-rw-r--r--src/distutils2/command/bdist_msi.py4
-rw-r--r--src/distutils2/command/bdist_wininst.py4
-rw-r--r--src/distutils2/command/build_py.py75
-rw-r--r--src/distutils2/command/cmd.py11
-rw-r--r--src/distutils2/command/sdist.py2
-rw-r--r--src/distutils2/command/upload.py2
-rw-r--r--src/distutils2/command/upload_docs.py135
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])