update sqlalchemy

This commit is contained in:
j 2016-02-22 16:43:36 +05:30
commit 3b436646a2
362 changed files with 37720 additions and 11021 deletions

View file

@ -2,7 +2,7 @@ __all__ = [
'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop',
'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts',
'sdist', 'setopt', 'test', 'install_egg_info', 'install_scripts',
'register', 'bdist_wininst', 'upload_docs',
'register', 'bdist_wininst', 'upload_docs', 'upload',
]
from distutils.command.bdist import bdist

View file

@ -1,5 +1,7 @@
from distutils.errors import DistutilsOptionError
from setuptools.extern.six.moves import map
from setuptools.command.setopt import edit_config, option_base, config_file

View file

@ -11,9 +11,10 @@ import os
import marshal
import textwrap
from setuptools.extern import six
from pkg_resources import get_build_platform, Distribution, ensure_directory
from pkg_resources import EntryPoint
from setuptools.compat import basestring
from setuptools.extension import Library
from setuptools import Command
@ -413,7 +414,7 @@ def iter_symbols(code):
for name in code.co_names:
yield name
for const in code.co_consts:
if isinstance(const, basestring):
if isinstance(const, six.string_types):
yield const
elif isinstance(const, CodeType):
for name in iter_symbols(const):

View file

@ -2,9 +2,14 @@ from glob import glob
from distutils.util import convert_path
import distutils.command.build_py as orig
import os
import sys
import fnmatch
import textwrap
import io
import distutils.errors
import collections
import itertools
from setuptools.extern.six.moves import map
try:
from setuptools.lib2to3_ex import Mixin2to3
@ -55,9 +60,10 @@ class build_py(orig.build_py, Mixin2to3):
self.byte_compile(orig.build_py.get_outputs(self, include_bytecode=0))
def __getattr__(self, attr):
if attr == 'data_files': # lazily compute data files
self.data_files = files = self._get_data_files()
return files
"lazily compute data files"
if attr == 'data_files':
self.data_files = self._get_data_files()
return self.data_files
return orig.build_py.__getattr__(self, attr)
def build_module(self, module, module_file, package):
@ -70,23 +76,21 @@ class build_py(orig.build_py, Mixin2to3):
def _get_data_files(self):
"""Generate list of '(package,src_dir,build_dir,filenames)' tuples"""
self.analyze_manifest()
data = []
for package in self.packages or ():
# Locate package source directory
src_dir = self.get_package_dir(package)
return list(map(self._get_pkg_data_files, self.packages or ()))
# Compute package build directory
build_dir = os.path.join(*([self.build_lib] + package.split('.')))
def _get_pkg_data_files(self, package):
# Locate package source directory
src_dir = self.get_package_dir(package)
# Length of path to strip from found files
plen = len(src_dir) + 1
# Compute package build directory
build_dir = os.path.join(*([self.build_lib] + package.split('.')))
# Strip directory from globbed filenames
filenames = [
file[plen:] for file in self.find_data_files(package, src_dir)
]
data.append((package, src_dir, build_dir, filenames))
return data
# Strip directory from globbed filenames
filenames = [
os.path.relpath(file, src_dir)
for file in self.find_data_files(package, src_dir)
]
return package, src_dir, build_dir, filenames
def find_data_files(self, package, src_dir):
"""Return filenames for package's data files in 'src_dir'"""
@ -157,17 +161,15 @@ class build_py(orig.build_py, Mixin2to3):
else:
return init_py
f = open(init_py, 'rbU')
if 'declare_namespace'.encode() not in f.read():
from distutils.errors import DistutilsError
raise DistutilsError(
with io.open(init_py, 'rb') as f:
contents = f.read()
if b'declare_namespace' not in contents:
raise distutils.errors.DistutilsError(
"Namespace package problem: %s is a namespace package, but "
"its\n__init__.py does not call declare_namespace()! Please "
'fix it.\n(See the setuptools manual under '
'"Namespace Packages" for details.)\n"' % (package,)
)
f.close()
return init_py
def initialize_options(self):
@ -182,20 +184,25 @@ class build_py(orig.build_py, Mixin2to3):
def exclude_data_files(self, package, src_dir, files):
"""Filter filenames for package's data files in 'src_dir'"""
globs = (self.exclude_package_data.get('', [])
+ self.exclude_package_data.get(package, []))
bad = []
for pattern in globs:
bad.extend(
fnmatch.filter(
files, os.path.join(src_dir, convert_path(pattern))
)
globs = (
self.exclude_package_data.get('', [])
+ self.exclude_package_data.get(package, [])
)
bad = set(
item
for pattern in globs
for item in fnmatch.filter(
files,
os.path.join(src_dir, convert_path(pattern)),
)
bad = dict.fromkeys(bad)
seen = {}
)
seen = collections.defaultdict(itertools.count)
return [
f for f in files if f not in bad
and f not in seen and seen.setdefault(f, 1) # ditch dupes
fn
for fn in files
if fn not in bad
# ditch dupes
and not next(seen[fn])
]

View file

@ -3,10 +3,12 @@ from distutils import log
from distutils.errors import DistutilsError, DistutilsOptionError
import os
import glob
import io
from setuptools.extern import six
from pkg_resources import Distribution, PathMetadata, normalize_path
from setuptools.command.easy_install import easy_install
from setuptools.compat import PY3
import setuptools
@ -53,8 +55,8 @@ class develop(easy_install):
# pick up setup-dir .egg files only: no .egg-info
self.package_index.scan(glob.glob('*.egg'))
self.egg_link = os.path.join(self.install_dir, ei.egg_name +
'.egg-link')
egg_link_fn = ei.egg_name + '.egg-link'
self.egg_link = os.path.join(self.install_dir, egg_link_fn)
self.egg_base = ei.egg_base
if self.egg_path is None:
self.egg_path = os.path.abspath(ei.egg_base)
@ -86,7 +88,7 @@ class develop(easy_install):
" installation directory", p, normalize_path(os.curdir))
def install_for_development(self):
if PY3 and getattr(self.distribution, 'use_2to3', False):
if six.PY3 and getattr(self.distribution, 'use_2to3', False):
# If we run 2to3 we can not do this inplace:
# Ensure metadata is up-to-date
@ -124,9 +126,8 @@ class develop(easy_install):
# create an .egg-link in the installation dir, pointing to our egg
log.info("Creating %s (link to %s)", self.egg_link, self.egg_base)
if not self.dry_run:
f = open(self.egg_link, "w")
f.write(self.egg_path + "\n" + self.setup_path)
f.close()
with open(self.egg_link, "w") as f:
f.write(self.egg_path + "\n" + self.setup_path)
# postprocess the installed distro, fixing up .pth, installing scripts,
# and handling requirements
self.process_distribution(None, self.dist, not self.no_deps)
@ -163,7 +164,33 @@ class develop(easy_install):
for script_name in self.distribution.scripts or []:
script_path = os.path.abspath(convert_path(script_name))
script_name = os.path.basename(script_path)
f = open(script_path, 'rU')
script_text = f.read()
f.close()
with io.open(script_path) as strm:
script_text = strm.read()
self.install_script(dist, script_name, script_text, script_path)
def install_wrapper_scripts(self, dist):
dist = VersionlessRequirement(dist)
return easy_install.install_wrapper_scripts(self, dist)
class VersionlessRequirement(object):
"""
Adapt a pkg_resources.Distribution to simply return the project
name as the 'requirement' so that scripts will work across
multiple versions.
>>> dist = Distribution(project_name='foo', version='1.0')
>>> str(dist.as_requirement())
'foo==1.0'
>>> adapted_dist = VersionlessRequirement(dist)
>>> str(adapted_dist.as_requirement())
'foo'
"""
def __init__(self, dist):
self.__dist = dist
def __getattr__(self, name):
return getattr(self.__dist, name)
def as_requirement(self):
return self.project_name

View file

@ -20,6 +20,7 @@ from distutils.errors import DistutilsArgError, DistutilsOptionError, \
from distutils.command.install import INSTALL_SCHEMES, SCHEME_KEYS
from distutils import log, dir_util
from distutils.command.build_scripts import first_line_re
from distutils.spawn import find_executable
import sys
import os
import zipimport
@ -39,6 +40,9 @@ import subprocess
import shlex
import io
from setuptools.extern import six
from setuptools.extern.six.moves import configparser, map
from setuptools import Command
from setuptools.sandbox import run_setup
from setuptools.py31compat import get_path, get_config_vars
@ -47,8 +51,6 @@ from setuptools.archive_util import unpack_archive
from setuptools.package_index import PackageIndex
from setuptools.package_index import URL_SCHEME
from setuptools.command import bdist_egg, egg_info
from setuptools.compat import (iteritems, maxsize, basestring, unicode,
reraise, PY2, PY3)
from pkg_resources import (
yield_lines, normalize_path, resource_string, ensure_directory,
get_distribution, find_distributions, Environment, Requirement,
@ -81,13 +83,13 @@ def samefile(p1, p2):
return norm_p1 == norm_p2
if PY2:
if six.PY2:
def _to_ascii(s):
return s
def isascii(s):
try:
unicode(s, 'ascii')
six.text_type(s, 'ascii')
return True
except UnicodeError:
return False
@ -319,7 +321,7 @@ class easy_install(Command):
self.local_index = Environment(self.shadow_path + sys.path)
if self.find_links is not None:
if isinstance(self.find_links, basestring):
if isinstance(self.find_links, six.string_types):
self.find_links = self.find_links.split()
else:
self.find_links = []
@ -412,7 +414,7 @@ class easy_install(Command):
try:
pid = os.getpid()
except:
pid = random.randint(0, maxsize)
pid = random.randint(0, sys.maxsize)
return os.path.join(self.install_dir, "test-easy-install-%s" % pid)
def warn_deprecated_options(self):
@ -760,9 +762,10 @@ class easy_install(Command):
return dst
def install_wrapper_scripts(self, dist):
if not self.exclude_scripts:
for args in ScriptWriter.best().get_args(dist):
self.write_script(*args)
if self.exclude_scripts:
return
for args in ScriptWriter.best().get_args(dist):
self.write_script(*args)
def install_script(self, dist, script_name, script_text, dev_path=None):
"""Generate a legacy script wrapper and install it"""
@ -770,8 +773,8 @@ class easy_install(Command):
is_script = is_python_script(script_text, script_name)
if is_script:
script_text = (ScriptWriter.get_header(script_text) +
self._load_template(dev_path) % locals())
body = self._load_template(dev_path) % locals()
script_text = ScriptWriter.get_header(script_text) + body
self.write_script(script_name, _to_ascii(script_text), 'b')
@staticmethod
@ -803,9 +806,8 @@ class easy_install(Command):
ensure_directory(target)
if os.path.exists(target):
os.unlink(target)
f = open(target, "w" + mode)
f.write(contents)
f.close()
with open(target, "w" + mode) as f:
f.write(contents)
chmod(target, 0o777 - mask)
def install_eggs(self, spec, dist_filename, tmpdir):
@ -1244,7 +1246,7 @@ class easy_install(Command):
f = open(sitepy, 'rb')
current = f.read()
# we want str, not bytes
if PY3:
if six.PY3:
current = current.decode()
f.close()
@ -1270,7 +1272,7 @@ class easy_install(Command):
if not self.user:
return
home = convert_path(os.path.expanduser("~"))
for name, path in iteritems(self.config_vars):
for name, path in six.iteritems(self.config_vars):
if path.startswith(home) and not os.path.isdir(path):
self.debug_print("os.makedirs('%s', 0o700)" % path)
os.makedirs(path, 0o700)
@ -1401,7 +1403,7 @@ def expand_paths(inputs):
def extract_wininst_cfg(dist_filename):
"""Extract configuration data from a bdist_wininst .exe
Returns a ConfigParser.RawConfigParser, or None
Returns a configparser.RawConfigParser, or None
"""
f = open(dist_filename, 'rb')
try:
@ -1414,15 +1416,12 @@ def extract_wininst_cfg(dist_filename):
return None
f.seek(prepended - 12)
from setuptools.compat import StringIO, ConfigParser
import struct
tag, cfglen, bmlen = struct.unpack("<iii", f.read(12))
if tag not in (0x1234567A, 0x1234567B):
return None # not a valid tag
f.seek(prepended - (12 + cfglen))
cfg = ConfigParser.RawConfigParser(
cfg = configparser.RawConfigParser(
{'version': '', 'target_version': ''})
try:
part = f.read(cfglen)
@ -1431,8 +1430,8 @@ def extract_wininst_cfg(dist_filename):
# Now the config is in bytes, but for RawConfigParser, it should
# be text, so decode it.
config = config.decode(sys.getfilesystemencoding())
cfg.readfp(StringIO(config))
except ConfigParser.Error:
cfg.readfp(six.StringIO(config))
except configparser.Error:
return None
if not cfg.has_section('metadata') or not cfg.has_section('Setup'):
return None
@ -1466,7 +1465,7 @@ def get_exe_prefixes(exe_filename):
continue
if parts[0].upper() in ('PURELIB', 'PLATLIB'):
contents = z.read(name)
if PY3:
if six.PY3:
contents = contents.decode()
for pth in yield_lines(contents):
pth = pth.strip().replace('\\', '/')
@ -1642,7 +1641,7 @@ def auto_chmod(func, arg, exc):
chmod(arg, stat.S_IWRITE)
return func(arg)
et, ev, _ = sys.exc_info()
reraise(et, (ev[0], ev[1] + (" %s %s" % (func, arg))))
six.reraise(et, (ev[0], ev[1] + (" %s %s" % (func, arg))))
def update_dist_caches(dist_path, fix_zipimporter_caches):
@ -1877,17 +1876,6 @@ def chmod(path, mode):
log.debug("chmod failed: %s", e)
def fix_jython_executable(executable, options):
warnings.warn("Use JythonCommandSpec", DeprecationWarning, stacklevel=2)
if not JythonCommandSpec.relevant():
return executable
cmd = CommandSpec.best().from_param(executable)
cmd.install_options(options)
return cmd.as_header().lstrip('#!').rstrip('\n')
class CommandSpec(list):
"""
A command spec for a #! header, specified as a list of arguments akin to
@ -1902,7 +1890,7 @@ class CommandSpec(list):
"""
Choose the best CommandSpec class based on environmental conditions.
"""
return cls if not JythonCommandSpec.relevant() else JythonCommandSpec
return cls
@classmethod
def _sys_executable(cls):
@ -1969,36 +1957,6 @@ class WindowsCommandSpec(CommandSpec):
split_args = dict(posix=False)
class JythonCommandSpec(CommandSpec):
@classmethod
def relevant(cls):
return (
sys.platform.startswith('java')
and
__import__('java').lang.System.getProperty('os.name') != 'Linux'
)
def as_header(self):
"""
Workaround Jython's sys.executable being a .sh (an invalid
shebang line interpreter)
"""
if not is_sh(self[0]):
return super(JythonCommandSpec, self).as_header()
if self.options:
# Can't apply the workaround, leave it broken
log.warn(
"WARNING: Unable to adapt shebang line for Jython,"
" the following script is NOT executable\n"
" see http://bugs.jython.org/issue1112 for"
" more information.")
return super(JythonCommandSpec, self).as_header()
items = ['/usr/bin/env'] + self + list(self.options)
return self._render(items)
class ScriptWriter(object):
"""
Encapsulates behavior around writing entry point scripts for console and
@ -2075,7 +2033,10 @@ class ScriptWriter(object):
"""
Select the best ScriptWriter for this environment.
"""
return WindowsScriptWriter.best() if sys.platform == 'win32' else cls
if sys.platform == 'win32' or (os.name == 'java' and os._name == 'nt'):
return WindowsScriptWriter.best()
else:
return cls
@classmethod
def _get_script_args(cls, type_, name, header, script_text):
@ -2125,8 +2086,8 @@ class WindowsScriptWriter(ScriptWriter):
blockers = [name + x for x in old]
yield name + ext, header + script_text, 't', blockers
@staticmethod
def _adjust_header(type_, orig_header):
@classmethod
def _adjust_header(cls, type_, orig_header):
"""
Make sure 'pythonw' is used for gui and and 'python' is used for
console (regardless of what sys.executable is).
@ -2137,11 +2098,19 @@ class WindowsScriptWriter(ScriptWriter):
pattern, repl = repl, pattern
pattern_ob = re.compile(re.escape(pattern), re.IGNORECASE)
new_header = pattern_ob.sub(string=orig_header, repl=repl)
return new_header if cls._use_header(new_header) else orig_header
@staticmethod
def _use_header(new_header):
"""
Should _adjust_header use the replaced header?
On non-windows systems, always use. On
Windows systems, only use the replaced header if it resolves
to an executable on the system.
"""
clean_header = new_header[2:-1].strip('"')
if sys.platform == 'win32' and not os.path.exists(clean_header):
# the adjusted version doesn't exist, so return the original
return orig_header
return new_header
return sys.platform != 'win32' or find_executable(clean_header)
class WindowsExecutableLauncherWriter(WindowsScriptWriter):
@ -2200,7 +2169,7 @@ def get_win_launcher(type):
def load_launcher_manifest(name):
manifest = pkg_resources.resource_string(__name__, 'launcher manifest.xml')
if PY2:
if six.PY2:
return manifest % vars()
else:
return manifest.decode('utf-8') % vars()

View file

@ -10,22 +10,30 @@ import distutils.filelist
import os
import re
import sys
import io
import warnings
import time
from setuptools.extern import six
from setuptools.extern.six.moves import map
from setuptools import Command
from setuptools.command.sdist import sdist
from setuptools.command.sdist import walk_revctrl
from setuptools.command.setopt import edit_config
from setuptools.command import bdist_egg
from pkg_resources import (
parse_requirements, safe_name, parse_version,
safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename)
import setuptools.unicode_utils as unicode_utils
from pkg_resources.extern import packaging
try:
from setuptools_svn import svn_utils
except ImportError:
pass
from setuptools import Command
from setuptools.command.sdist import sdist
from setuptools.compat import basestring, PY3, StringIO
from setuptools.command.sdist import walk_revctrl
from pkg_resources import (
parse_requirements, safe_name, parse_version,
safe_version, yield_lines, EntryPoint, iter_entry_points, to_filename)
import setuptools.unicode_utils as unicode_utils
from pkg_resources import packaging
class egg_info(Command):
description = "create a distribution's .egg-info directory"
@ -58,8 +66,6 @@ class egg_info(Command):
self.vtags = None
def save_version_info(self, filename):
from setuptools.command.setopt import edit_config
values = dict(
egg_info=dict(
tag_svn_revision=0,
@ -143,7 +149,7 @@ class egg_info(Command):
to the file.
"""
log.info("writing %s to %s", what, filename)
if PY3:
if six.PY3:
data = data.encode("utf-8")
if not self.dry_run:
f = open(filename, 'wb')
@ -184,12 +190,8 @@ class egg_info(Command):
if self.tag_build:
version += self.tag_build
if self.tag_svn_revision:
rev = self.get_svn_revision()
if rev: # is 0 if it's not an svn working copy
version += '-r%s' % rev
version += '-r%s' % self.get_svn_revision()
if self.tag_date:
import time
version += time.strftime("-%Y%m%d")
return version
@ -390,7 +392,6 @@ def write_pkg_info(cmd, basename, filename):
metadata.name, metadata.version = oldname, oldver
safe = getattr(cmd.distribution, 'zip_safe', None)
from setuptools.command import bdist_egg
bdist_egg.write_safety_flag(cmd.egg_info, safe)
@ -412,7 +413,7 @@ def _write_requirements(stream, reqs):
def write_requirements(cmd, basename, filename):
dist = cmd.distribution
data = StringIO()
data = six.StringIO()
_write_requirements(data, dist.install_requires)
extras_require = dist.extras_require or {}
for extra in sorted(extras_require):
@ -452,12 +453,12 @@ def write_arg(cmd, basename, filename, force=False):
def write_entries(cmd, basename, filename):
ep = cmd.distribution.entry_points
if isinstance(ep, basestring) or ep is None:
if isinstance(ep, six.string_types) or ep is None:
data = ep
elif ep is not None:
data = []
for section, contents in sorted(ep.items()):
if not isinstance(contents, basestring):
if not isinstance(contents, six.string_types):
contents = EntryPoint.parse_group(section, contents)
contents = '\n'.join(sorted(map(str, contents.values())))
data.append('[%s]\n%s\n\n' % (section, contents))
@ -467,14 +468,15 @@ def write_entries(cmd, basename, filename):
def get_pkg_info_revision():
# See if we can get a -r### off of PKG-INFO, in case this is an sdist of
# a subversion revision
#
"""
Get a -r### off of PKG-INFO Version in case this is an sdist of
a subversion revision.
"""
warnings.warn("get_pkg_info_revision is deprecated.", DeprecationWarning)
if os.path.exists('PKG-INFO'):
f = open('PKG-INFO', 'rU')
for line in f:
match = re.match(r"Version:.*-r(\d+)\s*$", line)
if match:
return int(match.group(1))
f.close()
with io.open('PKG-INFO') as f:
for line in f:
match = re.match(r"Version:.*-r(\d+)\s*$", line)
if match:
return int(match.group(1))
return 0

View file

@ -1,6 +1,8 @@
from distutils import log, dir_util
import os
from setuptools.extern.six.moves import map
from setuptools import Command
from setuptools.archive_util import unpack_archive
import pkg_resources
@ -27,7 +29,7 @@ class install_egg_info(Command):
).egg_name() + '.egg-info'
self.source = ei_cmd.egg_info
self.target = os.path.join(self.install_dir, basename)
self.outputs = [self.target]
self.outputs = []
def run(self):
self.run_command('egg_info')

View file

@ -79,6 +79,8 @@ class install_lib(orig.install_lib):
base = os.path.join('__pycache__', '__init__.' + imp.get_tag())
yield base + '.pyc'
yield base + '.pyo'
yield base + '.opt-1.pyc'
yield base + '.opt-2.pyc'
def copy_tree(
self, infile, outfile,

View file

@ -3,8 +3,9 @@ from distutils import log
from distutils.errors import DistutilsOptionError
import os
from setuptools.extern import six
from setuptools import Command
from setuptools.compat import basestring
class rotate(Command):
@ -36,7 +37,7 @@ class rotate(Command):
self.keep = int(self.keep)
except ValueError:
raise DistutilsOptionError("--keep must be an integer")
if isinstance(self.match, basestring):
if isinstance(self.match, six.string_types):
self.match = [
convert_path(p.strip()) for p in self.match.split(',')
]

View file

@ -3,8 +3,10 @@ from distutils import log
import distutils.command.sdist as orig
import os
import sys
import io
from setuptools.extern import six
from setuptools.compat import PY3
from setuptools.utils import cs_path_exists
import pkg_resources
@ -166,11 +168,8 @@ class sdist(orig.sdist):
if not os.path.isfile(self.manifest):
return False
fp = open(self.manifest, 'rbU')
try:
with io.open(self.manifest, 'rb') as fp:
first_line = fp.readline()
finally:
fp.close()
return (first_line !=
'# file GENERATED by distutils, do NOT edit\n'.encode())
@ -183,7 +182,7 @@ class sdist(orig.sdist):
manifest = open(self.manifest, 'rbU')
for line in manifest:
# The manifest must contain UTF-8. See #303.
if PY3:
if six.PY3:
try:
line = line.decode('UTF-8')
except UnicodeDecodeError:

View file

@ -4,6 +4,8 @@ from distutils.errors import DistutilsOptionError
import distutils
import os
from setuptools.extern.six.moves import configparser
from setuptools import Command
@ -37,10 +39,8 @@ def edit_config(filename, settings, dry_run=False):
while a dictionary lists settings to be changed or deleted in that section.
A setting of ``None`` means to delete that setting.
"""
from setuptools.compat import ConfigParser
log.debug("Reading configuration from %s", filename)
opts = ConfigParser.RawConfigParser()
opts = configparser.RawConfigParser()
opts.read([filename])
for section, options in settings.items():
if options is None:

View file

@ -2,11 +2,13 @@ from distutils.errors import DistutilsOptionError
from unittest import TestLoader
import sys
from setuptools.extern import six
from setuptools.extern.six.moves import map
from pkg_resources import (resource_listdir, resource_exists, normalize_path,
working_set, _namespace_packages,
add_activation_listener, require, EntryPoint)
from setuptools import Command
from setuptools.compat import PY3
from setuptools.py31compat import unittest_main
@ -41,6 +43,17 @@ class ScanningLoader(TestLoader):
return tests[0] # don't create a nested suite for only one return
# adapted from jaraco.classes.properties:NonDataProperty
class NonDataProperty(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, objtype=None):
if obj is None:
return self
return self.fget(obj)
class test(Command):
"""Command to run unit tests after in-place build"""
@ -78,7 +91,7 @@ class test(Command):
if self.test_runner is None:
self.test_runner = getattr(self.distribution, 'test_runner', None)
@property
@NonDataProperty
def test_args(self):
return list(self._test_args())
@ -89,7 +102,7 @@ class test(Command):
yield self.test_suite
def with_project_on_sys_path(self, func):
with_2to3 = PY3 and getattr(self.distribution, 'use_2to3', False)
with_2to3 = six.PY3 and getattr(self.distribution, 'use_2to3', False)
if with_2to3:
# If we run 2to3 we can not do this inplace:
@ -149,7 +162,7 @@ class test(Command):
# 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 PY3 and getattr(self.distribution, 'use_2to3', False):
if six.PY3 and getattr(self.distribution, 'use_2to3', False):
module = self.test_suite.split('.')[0]
if module in _namespace_packages:
del_modules = []

View file

@ -0,0 +1,23 @@
from distutils.command import upload as orig
class upload(orig.upload):
"""
Override default upload behavior to look up password
in the keyring if available.
"""
def finalize_options(self):
orig.upload.finalize_options(self)
self.password or self._load_password_from_keyring()
def _load_password_from_keyring(self):
"""
Attempt to load password from keyring. Suppress Exceptions.
"""
try:
keyring = __import__('keyring')
self.password = keyring.get_password(self.repository,
self.username)
except Exception:
pass

View file

@ -8,25 +8,26 @@ PyPI's pythonhosted.org).
from base64 import standard_b64encode
from distutils import log
from distutils.errors import DistutilsOptionError
from distutils.command.upload import upload
import os
import socket
import zipfile
import tempfile
import sys
import shutil
from setuptools.compat import httplib, urlparse, unicode, iteritems, PY3
from setuptools.extern import six
from setuptools.extern.six.moves import http_client, urllib
from pkg_resources import iter_entry_points
from .upload import upload
errors = 'surrogateescape' if PY3 else 'strict'
errors = 'surrogateescape' if six.PY3 else 'strict'
# 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):
if isinstance(s, six.text_type):
return s.encode(encoding, errors)
return s
@ -113,7 +114,7 @@ class upload_docs(upload):
# set up the authentication
credentials = b(self.username + ':' + self.password)
credentials = standard_b64encode(credentials)
if PY3:
if six.PY3:
credentials = credentials.decode('ascii')
auth = "Basic " + credentials
@ -122,7 +123,7 @@ class upload_docs(upload):
sep_boundary = b('\n--') + b(boundary)
end_boundary = sep_boundary + b('--')
body = []
for key, values in iteritems(data):
for key, values in six.iteritems(data):
title = '\nContent-Disposition: form-data; name="%s"' % key
# handle multiple entries for the same name
if not isinstance(values, list):
@ -150,12 +151,12 @@ class upload_docs(upload):
# We can't use urllib2 since we need to send the Basic
# auth right with the first request
schema, netloc, url, params, query, fragments = \
urlparse(self.repository)
urllib.parse.urlparse(self.repository)
assert not params and not query and not fragments
if schema == 'http':
conn = httplib.HTTPConnection(netloc)
conn = http_client.HTTPConnection(netloc)
elif schema == 'https':
conn = httplib.HTTPSConnection(netloc)
conn = http_client.HTTPSConnection(netloc)
else:
raise AssertionError("unsupported schema " + schema)