summaryrefslogtreecommitdiff
path: root/setuptools/command
diff options
context:
space:
mode:
Diffstat (limited to 'setuptools/command')
-rw-r--r--setuptools/command/bdist_egg.py12
-rw-r--r--setuptools/command/build_py.py6
-rwxr-xr-xsetuptools/command/easy_install.py5
-rwxr-xr-xsetuptools/command/egg_info.py39
-rwxr-xr-xsetuptools/command/sdist.py32
-rw-r--r--setuptools/command/test.py17
-rw-r--r--setuptools/command/upload_docs.py125
7 files changed, 165 insertions, 71 deletions
diff --git a/setuptools/command/bdist_egg.py b/setuptools/command/bdist_egg.py
index 0ee9c55b..17fae984 100644
--- a/setuptools/command/bdist_egg.py
+++ b/setuptools/command/bdist_egg.py
@@ -425,12 +425,12 @@ def scan_module(egg_dir, base, name, stubs):
return True # Extension module
pkg = base[len(egg_dir)+1:].replace(os.sep,'.')
module = pkg+(pkg and '.' or '')+os.path.splitext(name)[0]
- f = open(filename,'rb'); f.read(8) # skip magic & date
- try:
- code = marshal.load(f); f.close()
- except ValueError:
- f.seek(0); f.read(12) # skip magic & date & file size; file size added in Python 3.3
- code = marshal.load(f); f.close()
+ if sys.version_info < (3, 3):
+ skip = 8 # skip magic & date
+ else:
+ skip = 12 # skip magic & date & file size
+ f = open(filename,'rb'); f.read(skip)
+ code = marshal.load(f); f.close()
safe = True
symbols = dict.fromkeys(iter_symbols(code))
for bad in ['__file__', '__path__']:
diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py
index 505dd4f3..8751acd4 100644
--- a/setuptools/command/build_py.py
+++ b/setuptools/command/build_py.py
@@ -51,10 +51,8 @@ try:
if self.distribution.use_2to3_exclude_fixers is not None:
excluded_fixers.extend(self.distribution.use_2to3_exclude_fixers)
for fixer_name in excluded_fixers:
- if fixer_name not in self.fixer_names:
- log.warn("Excluded fixer %s not found", fixer_name)
- continue
- self.fixer_names.remove(fixer_name)
+ if fixer_name in self.fixer_names:
+ self.fixer_names.remove(fixer_name)
except ImportError:
class Mixin2to3:
diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py
index f2260236..337532bc 100755
--- a/setuptools/command/easy_install.py
+++ b/setuptools/command/easy_install.py
@@ -1522,7 +1522,10 @@ def get_exe_prefixes(exe_filename):
if name.endswith('-nspkg.pth'):
continue
if parts[0].upper() in ('PURELIB','PLATLIB'):
- for pth in yield_lines(z.read(name)):
+ contents = z.read(name)
+ if sys.version_info >= (3,):
+ contents = contents.decode()
+ for pth in yield_lines(contents):
pth = pth.strip().replace('\\','/')
if not pth.startswith('import'):
prefixes.append((('%s/%s/' % (parts[0],pth)), ''))
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index 46cdf4e0..0c2ea0cc 100755
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -9,7 +9,7 @@ from distutils.errors import *
from distutils import log
from setuptools.command.sdist import sdist
from distutils.util import convert_path
-from distutils.filelist import FileList
+from distutils.filelist import FileList as _FileList
from pkg_resources import parse_requirements, safe_name, parse_version, \
safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename
from sdist import walk_revctrl
@@ -162,7 +162,12 @@ class egg_info(Command):
os.unlink(filename)
def tagged_version(self):
- return safe_version(self.distribution.get_version() + self.vtags)
+ version = self.distribution.get_version()
+ # egg_info may be called more than once for a distribution,
+ # in which case the version string already contains all tags.
+ if self.vtags and version.endswith(self.vtags):
+ return safe_version(version)
+ return safe_version(version + self.vtags)
def run(self):
self.mkpath(self.egg_info)
@@ -269,16 +274,28 @@ class egg_info(Command):
self.broken_egg_info = self.egg_info
self.egg_info = bei # make it work for now
-class FileList(FileList):
+class FileList(_FileList):
"""File list that accepts only existing, platform-independent paths"""
def append(self, item):
if item.endswith('\r'): # Fix older sdists built on Windows
item = item[:-1]
path = convert_path(item)
- if os.path.exists(path):
- self.files.append(path)
+ if sys.version_info >= (3,):
+ try:
+ if os.path.exists(path) or os.path.exists(path.encode('utf-8')):
+ self.files.append(path)
+ except UnicodeEncodeError:
+ # Accept UTF-8 filenames even if LANG=C
+ if os.path.exists(path.encode('utf-8')):
+ self.files.append(path)
+ else:
+ log.warn("'%s' not %s encodable -- skipping", path,
+ sys.getfilesystemencoding())
+ else:
+ if os.path.exists(path):
+ self.files.append(path)
@@ -318,6 +335,18 @@ class manifest_maker(sdist):
by 'add_defaults()' and 'read_template()') to the manifest file
named by 'self.manifest'.
"""
+ # The manifest must be UTF-8 encodable. See #303.
+ if sys.version_info >= (3,):
+ files = []
+ for file in self.filelist.files:
+ try:
+ file.encode("utf-8")
+ except UnicodeEncodeError:
+ log.warn("'%s' not UTF-8 encodable -- skipping" % file)
+ else:
+ files.append(file)
+ self.filelist.files = files
+
files = self.filelist.files
if os.sep!='/':
files = [f.replace(os.sep,'/') for f in files]
diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py
index a176f635..2fa3771a 100755
--- a/setuptools/command/sdist.py
+++ b/setuptools/command/sdist.py
@@ -262,7 +262,39 @@ class sdist(_sdist):
self.get_finalized_command('egg_info').save_version_info(dest)
+ def _manifest_is_not_generated(self):
+ # check for special comment used in 2.7.1 and higher
+ if not os.path.isfile(self.manifest):
+ return False
+ fp = open(self.manifest, 'rbU')
+ try:
+ first_line = fp.readline()
+ finally:
+ fp.close()
+ return first_line != '# file GENERATED by distutils, do NOT edit\n'.encode()
+
+ def read_manifest(self):
+ """Read the manifest file (named by 'self.manifest') and use it to
+ fill in 'self.filelist', the list of files to include in the source
+ distribution.
+ """
+ log.info("reading manifest file '%s'", self.manifest)
+ manifest = open(self.manifest, 'rbU')
+ for line in manifest:
+ # The manifest must contain UTF-8. See #303.
+ if sys.version_info >= (3,):
+ try:
+ line = line.decode('UTF-8')
+ except UnicodeDecodeError:
+ log.warn("%r not UTF-8 decodable -- skipping" % line)
+ continue
+ # ignore comments and blank lines
+ line = line.strip()
+ if line.startswith('#') or not line:
+ continue
+ self.filelist.append(line)
+ manifest.close()
diff --git a/setuptools/command/test.py b/setuptools/command/test.py
index e5cb9bb5..a02ac142 100644
--- a/setuptools/command/test.py
+++ b/setuptools/command/test.py
@@ -2,6 +2,7 @@ from setuptools import Command
from distutils.errors import DistutilsOptionError
import sys
from pkg_resources import *
+from pkg_resources import _namespace_packages
from unittest import TestLoader, main
class ScanningLoader(TestLoader):
@@ -139,6 +140,22 @@ class test(Command):
def run_tests(self):
import unittest
+
+ # Purge modules under test from sys.modules. The test loader will
+ # re-import them from the build location. Required when 2to3 is used
+ # with namespace packages.
+ if sys.version_info >= (3,) and getattr(self.distribution, 'use_2to3', False):
+ module = self.test_args[-1].split('.')[0]
+ if module in _namespace_packages:
+ del_modules = []
+ if module in sys.modules:
+ del_modules.append(module)
+ module += '.'
+ for name in sys.modules:
+ if name.startswith(module):
+ del_modules.append(name)
+ map(sys.modules.__delitem__, del_modules)
+
loader_ep = EntryPoint.parse("x="+self.test_loader)
loader_class = loader_ep.load(require=False)
cks = loader_class()
diff --git a/setuptools/command/upload_docs.py b/setuptools/command/upload_docs.py
index 213f7b58..98fb7233 100644
--- a/setuptools/command/upload_docs.py
+++ b/setuptools/command/upload_docs.py
@@ -9,10 +9,13 @@ import os
import socket
import zipfile
import httplib
-import base64
import urlparse
import tempfile
import sys
+import shutil
+
+from base64 import standard_b64encode
+from pkg_resources import iter_entry_points
from distutils import log
from distutils.errors import DistutilsOptionError
@@ -22,20 +25,13 @@ try:
except ImportError:
from setuptools.command.upload import upload
-_IS_PYTHON3 = sys.version > '3'
-
-try:
- bytes
-except NameError:
- bytes = str
-def b(str_or_bytes):
- """Return bytes by either encoding the argument as ASCII or simply return
- the argument as-is."""
- if not isinstance(str_or_bytes, bytes):
- return str_or_bytes.encode('ascii')
- else:
- return str_or_bytes
+# This is not just a replacement for byte literals
+# but works as a general purpose encoder
+def b(s, encoding='utf-8'):
+ if isinstance(s, unicode):
+ return s.encode(encoding)
+ return s
class upload_docs(upload):
@@ -51,40 +47,62 @@ class upload_docs(upload):
]
boolean_options = upload.boolean_options
+ def has_sphinx(self):
+ if self.upload_dir is None:
+ for ep in iter_entry_points('distutils.commands', 'build_sphinx'):
+ return True
+
+ sub_commands = [('build_sphinx', has_sphinx)]
+
def initialize_options(self):
upload.initialize_options(self)
self.upload_dir = None
+ self.target_dir = None
def finalize_options(self):
upload.finalize_options(self)
if self.upload_dir is None:
- build = self.get_finalized_command('build')
- self.upload_dir = os.path.join(build.build_base, 'docs')
- self.mkpath(self.upload_dir)
- self.ensure_dirname('upload_dir')
- self.announce('Using upload directory %s' % self.upload_dir)
+ if self.has_sphinx():
+ build_sphinx = self.get_finalized_command('build_sphinx')
+ self.target_dir = build_sphinx.builder_target_dir
+ else:
+ build = self.get_finalized_command('build')
+ self.target_dir = os.path.join(build.build_base, 'docs')
+ else:
+ self.ensure_dirname('upload_dir')
+ self.target_dir = self.upload_dir
+ self.announce('Using upload directory %s' % self.target_dir)
- def create_zipfile(self):
- name = self.distribution.metadata.get_name()
- tmp_dir = tempfile.mkdtemp()
- tmp_file = os.path.join(tmp_dir, "%s.zip" % name)
- zip_file = zipfile.ZipFile(tmp_file, "w")
- for root, dirs, files in os.walk(self.upload_dir):
- if root == self.upload_dir and not files:
- raise DistutilsOptionError(
- "no files found in upload directory '%s'"
- % self.upload_dir)
- for name in files:
- full = os.path.join(root, name)
- relative = root[len(self.upload_dir):].lstrip(os.path.sep)
- dest = os.path.join(relative, name)
- zip_file.write(full, dest)
- zip_file.close()
- return tmp_file
+ def create_zipfile(self, filename):
+ zip_file = zipfile.ZipFile(filename, "w")
+ try:
+ self.mkpath(self.target_dir) # just in case
+ for root, dirs, files in os.walk(self.target_dir):
+ if root == self.target_dir and not files:
+ raise DistutilsOptionError(
+ "no files found in upload directory '%s'"
+ % self.target_dir)
+ for name in files:
+ full = os.path.join(root, name)
+ relative = root[len(self.target_dir):].lstrip(os.path.sep)
+ dest = os.path.join(relative, name)
+ zip_file.write(full, dest)
+ finally:
+ zip_file.close()
def run(self):
- zip_file = self.create_zipfile()
- self.upload_file(zip_file)
+ # Run sub commands
+ for cmd_name in self.get_sub_commands():
+ self.run_command(cmd_name)
+
+ tmp_dir = tempfile.mkdtemp()
+ name = self.distribution.metadata.get_name()
+ zip_file = os.path.join(tmp_dir, "%s.zip" % name)
+ try:
+ self.create_zipfile(zip_file)
+ self.upload_file(zip_file)
+ finally:
+ shutil.rmtree(tmp_dir)
def upload_file(self, filename):
content = open(filename, 'rb').read()
@@ -95,36 +113,33 @@ class upload_docs(upload):
'content': (os.path.basename(filename), content),
}
# set up the authentication
- credentials = self.username + ':' + self.password
- if _IS_PYTHON3: # base64 only works with bytes in Python 3.
- encoded_creds = base64.encodebytes(credentials.encode('utf8'))
- auth = bytes("Basic ")
- else:
- encoded_creds = base64.encodestring(credentials)
- auth = "Basic "
- auth += encoded_creds.strip()
+ credentials = b(self.username + ':' + self.password)
+ credentials = standard_b64encode(credentials)
+ if sys.version_info >= (3,):
+ credentials = credentials.decode('ascii')
+ auth = "Basic " + credentials
# Build up the MIME payload for the POST data
- boundary = b('--------------GHSKFJDLGDS7543FJKLFHRE75642756743254')
- sep_boundary = b('\n--') + boundary
+ boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
+ sep_boundary = b('\n--') + b(boundary)
end_boundary = sep_boundary + b('--')
body = []
- for key, values in data.items():
+ for key, values in data.iteritems():
+ title = '\nContent-Disposition: form-data; name="%s"' % key
# handle multiple entries for the same name
if type(values) != type([]):
values = [values]
for value in values:
if type(value) is tuple:
- fn = b(';filename="%s"' % value[0])
+ title += '; filename="%s"' % value[0]
value = value[1]
else:
- fn = b("")
+ value = b(value)
body.append(sep_boundary)
- body.append(b('\nContent-Disposition: form-data; name="%s"'%key))
- body.append(fn)
+ body.append(b(title))
body.append(b("\n\n"))
- body.append(b(value))
- if value and value[-1] == b('\r'):
+ body.append(value)
+ if value and value[-1:] == b('\r'):
body.append(b('\n')) # write an extra newline (lurve Macs)
body.append(end_boundary)
body.append(b("\n"))