branch merge

This commit is contained in:
Brian Curtin 2011-11-07 14:19:46 -06:00
commit ca0fbc02e9
38 changed files with 202 additions and 259 deletions

View file

@ -295,7 +295,8 @@ Archiving operations
*owner* and *group* are used when creating a tar archive. By default, *owner* and *group* are used when creating a tar archive. By default,
uses the current owner and group. uses the current owner and group.
*logger* is an instance of :class:`logging.Logger`. *logger* must be an object compatible with :pep:`282`, usually an instance of
:class:`logging.Logger`.
.. versionadded:: 3.2 .. versionadded:: 3.2

View file

@ -398,9 +398,8 @@ def hook_compressed(filename, mode):
def hook_encoded(encoding): def hook_encoded(encoding):
import codecs
def openhook(filename, mode): def openhook(filename, mode):
return codecs.open(filename, mode, encoding) return open(filename, mode, encoding=encoding)
return openhook return openhook

View file

@ -1,4 +1,4 @@
"""HTTP cookie handling for web clients. r"""HTTP cookie handling for web clients.
This module has (now fairly distant) origins in Gisle Aas' Perl module This module has (now fairly distant) origins in Gisle Aas' Perl module
HTTP::Cookies, from the libwww-perl library. HTTP::Cookies, from the libwww-perl library.

View file

@ -35,11 +35,6 @@ __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
'info', 'log', 'makeLogRecord', 'setLoggerClass', 'warn', 'warning', 'info', 'log', 'makeLogRecord', 'setLoggerClass', 'warn', 'warning',
'getLogRecordFactory', 'setLogRecordFactory', 'lastResort'] 'getLogRecordFactory', 'setLogRecordFactory', 'lastResort']
try:
import codecs
except ImportError: #pragma: no cover
codecs = None
try: try:
import threading import threading
except ImportError: #pragma: no cover except ImportError: #pragma: no cover
@ -954,8 +949,6 @@ class FileHandler(StreamHandler):
""" """
#keep the absolute path, otherwise derived classes which use this #keep the absolute path, otherwise derived classes which use this
#may come a cropper when the current directory changes #may come a cropper when the current directory changes
if codecs is None: #pragma: no cover
encoding = None
self.baseFilename = os.path.abspath(filename) self.baseFilename = os.path.abspath(filename)
self.mode = mode self.mode = mode
self.encoding = encoding self.encoding = encoding
@ -983,11 +976,7 @@ class FileHandler(StreamHandler):
Open the current base file with the (original) mode and encoding. Open the current base file with the (original) mode and encoding.
Return the resulting stream. Return the resulting stream.
""" """
if self.encoding is None: return open(self.baseFilename, self.mode, encoding=self.encoding)
stream = open(self.baseFilename, self.mode)
else:
stream = codecs.open(self.baseFilename, self.mode, self.encoding)
return stream
def emit(self, record): def emit(self, record):
""" """

View file

@ -24,8 +24,8 @@ Copyright (C) 2001-2010 Vinay Sajip. All Rights Reserved.
To use, simply 'import logging' and log away! To use, simply 'import logging' and log away!
""" """
import sys, logging, logging.handlers, socket, struct, os, traceback, re import sys, logging, logging.handlers, socket, struct, traceback, re
import types, io import io
try: try:
import _thread as thread import _thread as thread
@ -98,9 +98,6 @@ def _resolve(name):
def _strip_spaces(alist): def _strip_spaces(alist):
return map(lambda x: x.strip(), alist) return map(lambda x: x.strip(), alist)
def _encoded(s):
return s if isinstance(s, str) else s.encode('utf-8')
def _create_formatters(cp): def _create_formatters(cp):
"""Create and return formatters""" """Create and return formatters"""
flist = cp["formatters"]["keys"] flist = cp["formatters"]["keys"]
@ -215,7 +212,7 @@ def _install_loggers(cp, handlers, disable_existing):
#avoid disabling child loggers of explicitly #avoid disabling child loggers of explicitly
#named loggers. With a sorted list it is easier #named loggers. With a sorted list it is easier
#to find the child loggers. #to find the child loggers.
existing.sort(key=_encoded) existing.sort()
#We'll keep the list of existing loggers #We'll keep the list of existing loggers
#which are children of named loggers here... #which are children of named loggers here...
child_loggers = [] child_loggers = []
@ -588,7 +585,7 @@ class DictConfigurator(BaseConfigurator):
#avoid disabling child loggers of explicitly #avoid disabling child loggers of explicitly
#named loggers. With a sorted list it is easier #named loggers. With a sorted list it is easier
#to find the child loggers. #to find the child loggers.
existing.sort(key=_encoded) existing.sort()
#We'll keep the list of existing loggers #We'll keep the list of existing loggers
#which are children of named loggers here... #which are children of named loggers here...
child_loggers = [] child_loggers = []
@ -804,7 +801,6 @@ def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
struct.pack(">L", n), followed by the config file. struct.pack(">L", n), followed by the config file.
Uses fileConfig() to do the grunt work. Uses fileConfig() to do the grunt work.
""" """
import tempfile
try: try:
conn = self.connection conn = self.connection
chunk = conn.recv(4) chunk = conn.recv(4)

View file

@ -25,6 +25,7 @@ To use, simply 'import logging.handlers' and log away!
""" """
import logging, socket, os, pickle, struct, time, re import logging, socket, os, pickle, struct, time, re
from codecs import BOM_UTF8
from stat import ST_DEV, ST_INO, ST_MTIME from stat import ST_DEV, ST_INO, ST_MTIME
import queue import queue
try: try:
@ -32,11 +33,6 @@ try:
except ImportError: #pragma: no cover except ImportError: #pragma: no cover
threading = None threading = None
try:
import codecs
except ImportError: #pragma: no cover
codecs = None
# #
# Some constants... # Some constants...
# #
@ -60,8 +56,6 @@ class BaseRotatingHandler(logging.FileHandler):
""" """
Use the specified filename for streamed logging Use the specified filename for streamed logging
""" """
if codecs is None: #pragma: no cover
encoding = None
logging.FileHandler.__init__(self, filename, mode, encoding, delay) logging.FileHandler.__init__(self, filename, mode, encoding, delay)
self.mode = mode self.mode = mode
self.encoding = encoding self.encoding = encoding
@ -793,9 +787,7 @@ class SysLogHandler(logging.Handler):
prio = prio.encode('utf-8') prio = prio.encode('utf-8')
# Message is a string. Convert to bytes as required by RFC 5424 # Message is a string. Convert to bytes as required by RFC 5424
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
if codecs: msg = prio + BOM_UTF8 + msg
msg = codecs.BOM_UTF8 + msg
msg = prio + msg
try: try:
if self.unixsocket: if self.unixsocket:
try: try:

View file

@ -126,7 +126,7 @@ class bdist(Command):
# Reinitialize and run each command. # Reinitialize and run each command.
for i in range(len(self.formats)): for i in range(len(self.formats)):
cmd_name = commands[i] cmd_name = commands[i]
sub_cmd = self.get_reinitialized_command(cmd_name) sub_cmd = self.reinitialize_command(cmd_name)
sub_cmd.format = self.formats[i] sub_cmd.format = self.formats[i]
# passing the owner and group names for tar archiving # passing the owner and group names for tar archiving

View file

@ -80,8 +80,8 @@ class bdist_dumb(Command):
if not self.skip_build: if not self.skip_build:
self.run_command('build') self.run_command('build')
install = self.get_reinitialized_command('install_dist', install = self.reinitialize_command('install_dist',
reinit_subcommands=True) reinit_subcommands=True)
install.root = self.bdist_dir install.root = self.bdist_dir
install.skip_build = self.skip_build install.skip_build = self.skip_build
install.warn_dir = False install.warn_dir = False

View file

@ -183,13 +183,13 @@ class bdist_msi(Command):
if not self.skip_build: if not self.skip_build:
self.run_command('build') self.run_command('build')
install = self.get_reinitialized_command('install_dist', install = self.reinitialize_command('install_dist',
reinit_subcommands=True) reinit_subcommands=True)
install.prefix = self.bdist_dir install.prefix = self.bdist_dir
install.skip_build = self.skip_build install.skip_build = self.skip_build
install.warn_dir = False install.warn_dir = False
install_lib = self.get_reinitialized_command('install_lib') install_lib = self.reinitialize_command('install_lib')
# we do not want to include pyc or pyo files # we do not want to include pyc or pyo files
install_lib.compile = False install_lib.compile = False
install_lib.optimize = 0 install_lib.optimize = 0

View file

@ -115,14 +115,13 @@ class bdist_wininst(Command):
if not self.skip_build: if not self.skip_build:
self.run_command('build') self.run_command('build')
install = self.get_reinitialized_command('install', install = self.reinitialize_command('install', reinit_subcommands=True)
reinit_subcommands=True)
install.root = self.bdist_dir install.root = self.bdist_dir
install.skip_build = self.skip_build install.skip_build = self.skip_build
install.warn_dir = False install.warn_dir = False
install.plat_name = self.plat_name install.plat_name = self.plat_name
install_lib = self.get_reinitialized_command('install_lib') install_lib = self.reinitialize_command('install_lib')
# we do not want to include pyc or pyo files # we do not want to include pyc or pyo files
install_lib.compile = False install_lib.compile = False
install_lib.optimize = 0 install_lib.optimize = 0

View file

@ -318,8 +318,8 @@ class Command:
cmd_obj.ensure_finalized() cmd_obj.ensure_finalized()
return cmd_obj return cmd_obj
def get_reinitialized_command(self, command, reinit_subcommands=False): def reinitialize_command(self, command, reinit_subcommands=False):
return self.distribution.get_reinitialized_command( return self.distribution.reinitialize_command(
command, reinit_subcommands) command, reinit_subcommands)
def run_command(self, command): def run_command(self, command):

View file

@ -55,9 +55,7 @@ class install_dist(Command):
('install-data=', None, ('install-data=', None,
"installation directory for data files"), "installation directory for data files"),
# Byte-compilation options -- see install_lib.py for details, as # Byte-compilation options -- see install_lib for details
# these are duplicated from there (but only install_lib does
# anything with them).
('compile', 'c', "compile .py to .pyc [default]"), ('compile', 'c', "compile .py to .pyc [default]"),
('no-compile', None, "don't compile .py files"), ('no-compile', None, "don't compile .py files"),
('optimize=', 'O', ('optimize=', 'O',

View file

@ -16,8 +16,8 @@ class install_distinfo(Command):
description = 'create a .dist-info directory for the distribution' description = 'create a .dist-info directory for the distribution'
user_options = [ user_options = [
('distinfo-dir=', None, ('install-dir=', None,
"directory where the the .dist-info directory will be installed"), "directory where the the .dist-info directory will be created"),
('installer=', None, ('installer=', None,
"the name of the installer"), "the name of the installer"),
('requested', None, ('requested', None,
@ -35,7 +35,7 @@ class install_distinfo(Command):
negative_opt = {'no-requested': 'requested'} negative_opt = {'no-requested': 'requested'}
def initialize_options(self): def initialize_options(self):
self.distinfo_dir = None self.install_dir = None
self.installer = None self.installer = None
self.requested = None self.requested = None
self.no_record = None self.no_record = None
@ -46,8 +46,7 @@ class install_distinfo(Command):
self.set_undefined_options('install_dist', self.set_undefined_options('install_dist',
'installer', 'requested', 'no_record') 'installer', 'requested', 'no_record')
self.set_undefined_options('install_lib', self.set_undefined_options('install_lib', 'install_dir')
('install_dir', 'distinfo_dir'))
if self.installer is None: if self.installer is None:
# FIXME distutils or packaging? # FIXME distutils or packaging?
@ -64,26 +63,26 @@ class install_distinfo(Command):
basename = metadata.get_fullname(filesafe=True) + ".dist-info" basename = metadata.get_fullname(filesafe=True) + ".dist-info"
self.distinfo_dir = os.path.join(self.distinfo_dir, basename) self.install_dir = os.path.join(self.install_dir, basename)
def run(self): def run(self):
target = self.distinfo_dir target = self.install_dir
if os.path.isdir(target) and not os.path.islink(target): if os.path.isdir(target) and not os.path.islink(target):
if not self.dry_run: if not self.dry_run:
rmtree(target) rmtree(target)
elif os.path.exists(target): elif os.path.exists(target):
self.execute(os.unlink, (self.distinfo_dir,), self.execute(os.unlink, (self.install_dir,),
"removing " + target) "removing " + target)
self.execute(os.makedirs, (target,), "creating " + target) self.execute(os.makedirs, (target,), "creating " + target)
metadata_path = os.path.join(self.distinfo_dir, 'METADATA') metadata_path = os.path.join(self.install_dir, 'METADATA')
self.execute(self.distribution.metadata.write, (metadata_path,), self.execute(self.distribution.metadata.write, (metadata_path,),
"creating " + metadata_path) "creating " + metadata_path)
self.outfiles.append(metadata_path) self.outfiles.append(metadata_path)
installer_path = os.path.join(self.distinfo_dir, 'INSTALLER') installer_path = os.path.join(self.install_dir, 'INSTALLER')
logger.info('creating %s', installer_path) logger.info('creating %s', installer_path)
if not self.dry_run: if not self.dry_run:
with open(installer_path, 'w') as f: with open(installer_path, 'w') as f:
@ -91,7 +90,7 @@ class install_distinfo(Command):
self.outfiles.append(installer_path) self.outfiles.append(installer_path)
if self.requested: if self.requested:
requested_path = os.path.join(self.distinfo_dir, 'REQUESTED') requested_path = os.path.join(self.install_dir, 'REQUESTED')
logger.info('creating %s', requested_path) logger.info('creating %s', requested_path)
if not self.dry_run: if not self.dry_run:
open(requested_path, 'wb').close() open(requested_path, 'wb').close()
@ -100,7 +99,7 @@ class install_distinfo(Command):
if not self.no_resources: if not self.no_resources:
install_data = self.get_finalized_command('install_data') install_data = self.get_finalized_command('install_data')
if install_data.get_resources_out() != []: if install_data.get_resources_out() != []:
resources_path = os.path.join(self.distinfo_dir, resources_path = os.path.join(self.install_dir,
'RESOURCES') 'RESOURCES')
logger.info('creating %s', resources_path) logger.info('creating %s', resources_path)
if not self.dry_run: if not self.dry_run:
@ -114,7 +113,7 @@ class install_distinfo(Command):
self.outfiles.append(resources_path) self.outfiles.append(resources_path)
if not self.no_record: if not self.no_record:
record_path = os.path.join(self.distinfo_dir, 'RECORD') record_path = os.path.join(self.install_dir, 'RECORD')
logger.info('creating %s', record_path) logger.info('creating %s', record_path)
if not self.dry_run: if not self.dry_run:
with open(record_path, 'w', encoding='utf-8') as f: with open(record_path, 'w', encoding='utf-8') as f:

View file

@ -56,7 +56,7 @@ class test(Command):
prev_syspath = sys.path[:] prev_syspath = sys.path[:]
try: try:
# build release # build release
build = self.get_reinitialized_command('build') build = self.reinitialize_command('build')
self.run_command('build') self.run_command('build')
sys.path.insert(0, build.build_lib) sys.path.insert(0, build.build_lib)

View file

@ -30,6 +30,7 @@ from textwrap import dedent
from tokenize import detect_encoding from tokenize import detect_encoding
from configparser import RawConfigParser from configparser import RawConfigParser
from packaging import logger
# importing this with an underscore as it should be replaced by the # importing this with an underscore as it should be replaced by the
# dict form or another structures for all purposes # dict form or another structures for all purposes
from packaging._trove import all_classifiers as _CLASSIFIERS_LIST from packaging._trove import all_classifiers as _CLASSIFIERS_LIST
@ -124,7 +125,7 @@ def ask_yn(question, default=None, helptext=None):
if answer and answer[0].lower() in ('y', 'n'): if answer and answer[0].lower() in ('y', 'n'):
return answer[0].lower() return answer[0].lower()
print('\nERROR: You must select "Y" or "N".\n') logger.error('You must select "Y" or "N".')
# XXX use util.ask # XXX use util.ask
@ -147,10 +148,7 @@ def ask(question, default=None, helptext=None, required=True,
helptext = helptext.strip("\n") helptext = helptext.strip("\n")
while True: while True:
sys.stdout.write(prompt) line = input(prompt).strip()
sys.stdout.flush()
line = sys.stdin.readline().strip()
if line == '?': if line == '?':
print('=' * 70) print('=' * 70)
print(helptext) print(helptext)
@ -271,9 +269,10 @@ class MainProgram:
def _write_cfg(self): def _write_cfg(self):
if os.path.exists(_FILENAME): if os.path.exists(_FILENAME):
if os.path.exists('%s.old' % _FILENAME): if os.path.exists('%s.old' % _FILENAME):
print("ERROR: %(name)s.old backup exists, please check that " message = ("ERROR: %(name)s.old backup exists, please check "
"current %(name)s is correct and remove %(name)s.old" % "that current %(name)s is correct and remove "
{'name': _FILENAME}) "%(name)s.old" % {'name': _FILENAME})
logger.error(message)
return return
shutil.move(_FILENAME, '%s.old' % _FILENAME) shutil.move(_FILENAME, '%s.old' % _FILENAME)
@ -320,7 +319,7 @@ class MainProgram:
fp.write('\n') fp.write('\n')
os.chmod(_FILENAME, 0o644) os.chmod(_FILENAME, 0o644)
print('Wrote "%s".' % _FILENAME) logger.info('Wrote "%s".' % _FILENAME)
def convert_py_to_cfg(self): def convert_py_to_cfg(self):
"""Generate a setup.cfg from an existing setup.py. """Generate a setup.cfg from an existing setup.py.
@ -614,8 +613,8 @@ class MainProgram:
break break
if len(found_list) == 0: if len(found_list) == 0:
print('ERROR: Could not find a matching license for "%s"' % logger.error('Could not find a matching license for "%s"' %
license) license)
continue continue
question = 'Matching licenses:\n\n' question = 'Matching licenses:\n\n'
@ -636,8 +635,8 @@ class MainProgram:
try: try:
index = found_list[int(choice) - 1] index = found_list[int(choice) - 1]
except ValueError: except ValueError:
print("ERROR: Invalid selection, type a number from the list " logger.error(
"above.") "Invalid selection, type a number from the list above.")
classifiers.add(_CLASSIFIERS_LIST[index]) classifiers.add(_CLASSIFIERS_LIST[index])
@ -660,8 +659,8 @@ class MainProgram:
classifiers.add(key) classifiers.add(key)
return return
except (IndexError, ValueError): except (IndexError, ValueError):
print("ERROR: Invalid selection, type a single digit " logger.error(
"number.") "Invalid selection, type a single digit number.")
def main(): def main():
@ -675,7 +674,3 @@ def main():
# program.write_setup_script() # program.write_setup_script()
# packaging.util.cfg_to_args() # packaging.util.cfg_to_args()
program() program()
if __name__ == '__main__':
main()

View file

@ -224,6 +224,7 @@ def dependent_dists(dists, dist):
def main(): def main():
# XXX move to run._graph
from packaging.database import get_distributions from packaging.database import get_distributions
tempout = StringIO() tempout = StringIO()
try: try:
@ -267,7 +268,3 @@ def main():
else: else:
print('Supported option: -d [filename]') print('Supported option: -d [filename]')
sys.exit(1) sys.exit(1)
if __name__ == '__main__':
main()

View file

@ -636,9 +636,9 @@ Common commands: (see '--help-commands' for more)
except ValueError as msg: except ValueError as msg:
raise PackagingOptionError(msg) raise PackagingOptionError(msg)
def get_reinitialized_command(self, command, reinit_subcommands=False): def reinitialize_command(self, command, reinit_subcommands=False):
"""Reinitializes a command to the state it was in when first """Reinitializes a command to the state it was in when first
returned by 'get_command_obj()': ie., initialized but not yet returned by 'get_command_obj()': i.e., initialized but not yet
finalized. This provides the opportunity to sneak option finalized. This provides the opportunity to sneak option
values in programmatically, overriding or supplementing values in programmatically, overriding or supplementing
user-supplied values from the config files and command line. user-supplied values from the config files and command line.
@ -650,10 +650,11 @@ Common commands: (see '--help-commands' for more)
'reinit_subcommands' is true, also reinitializes the command's 'reinit_subcommands' is true, also reinitializes the command's
sub-commands, as declared by the 'sub_commands' class attribute (if sub-commands, as declared by the 'sub_commands' class attribute (if
it has one). See the "install_dist" command for an example. Only it has one). See the "install_dist" command for an example. Only
reinitializes the sub-commands that actually matter, ie. those reinitializes the sub-commands that actually matter, i.e. those
whose test predicates return true. whose test predicate return true.
Returns the reinitialized command object. Returns the reinitialized command object. It will be the same
object as the one stored in the self.command_obj attribute.
""" """
if not isinstance(command, Command): if not isinstance(command, Command):
command_name = command command_name = command
@ -671,7 +672,7 @@ Common commands: (see '--help-commands' for more)
if reinit_subcommands: if reinit_subcommands:
for sub in command.get_sub_commands(): for sub in command.get_sub_commands():
self.get_reinitialized_command(sub, reinit_subcommands) self.reinitialize_command(sub, reinit_subcommands)
return command return command

View file

@ -527,12 +527,3 @@ def install(project):
logger.info('%r conflicts with %s', project, ','.join(projects)) logger.info('%r conflicts with %s', project, ','.join(projects))
return True return True
def _main(**attrs):
if 'script_args' not in attrs:
attrs['requirements'] = sys.argv[1]
get_infos(**attrs)
if __name__ == '__main__':
_main()

View file

@ -41,6 +41,9 @@ import tempfile
import sysconfig import sysconfig
from packaging.dist import Distribution from packaging.dist import Distribution
from packaging.util import resolve_name
from packaging.command import set_command, _COMMANDS
from packaging.tests import unittest from packaging.tests import unittest
from test.support import requires_zlib, unlink from test.support import requires_zlib, unlink
@ -49,9 +52,10 @@ __all__ = [
# TestCase mixins # TestCase mixins
'LoggingCatcher', 'TempdirManager', 'EnvironRestorer', 'LoggingCatcher', 'TempdirManager', 'EnvironRestorer',
# mocks # mocks
'DummyCommand', 'TestDistribution', 'DummyCommand', 'TestDistribution', 'Inputs',
# misc. functions and decorators # misc. functions and decorators
'fake_dec', 'create_distribution', 'copy_xxmodule_c', 'fixup_build_ext', 'fake_dec', 'create_distribution', 'use_command',
'copy_xxmodule_c', 'fixup_build_ext',
# imported from this module for backport purposes # imported from this module for backport purposes
'unittest', 'requires_zlib', 'skip_2to3_optimize', 'skip_unless_symlink', 'unittest', 'requires_zlib', 'skip_2to3_optimize', 'skip_unless_symlink',
] ]
@ -247,7 +251,7 @@ class DummyCommand:
Useful for mocking one dependency command in the tests for another Useful for mocking one dependency command in the tests for another
command, see e.g. the dummy build command in test_build_scripts. command, see e.g. the dummy build command in test_build_scripts.
""" """
# XXX does not work with dist.get_reinitialized_command, which typechecks # XXX does not work with dist.reinitialize_command, which typechecks
# and wants a finalized attribute # and wants a finalized attribute
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -270,6 +274,22 @@ class TestDistribution(Distribution):
return self._config_files return self._config_files
class Inputs:
"""Fakes user inputs."""
# TODO document usage
# TODO use context manager or something for auto cleanup
def __init__(self, *answers):
self.answers = answers
self.index = 0
def __call__(self, prompt=''):
try:
return self.answers[self.index]
finally:
self.index += 1
def create_distribution(configfiles=()): def create_distribution(configfiles=()):
"""Prepares a distribution with given config files parsed.""" """Prepares a distribution with given config files parsed."""
d = TestDistribution() d = TestDistribution()
@ -280,6 +300,15 @@ def create_distribution(configfiles=()):
return d return d
def use_command(testcase, fullname):
"""Register command at *fullname* for the duration of a test."""
set_command(fullname)
# XXX maybe set_command should return the class object
name = resolve_name(fullname).get_command_name()
# XXX maybe we need a public API to remove commands
testcase.addCleanup(_COMMANDS.__delitem__, name)
def fake_dec(*args, **kw): def fake_dec(*args, **kw):
"""Fake decorator""" """Fake decorator"""
def _wrap(func): def _wrap(func):

View file

@ -3,7 +3,6 @@ import sys
import site import site
import sysconfig import sysconfig
import textwrap import textwrap
from io import StringIO
from packaging.dist import Distribution from packaging.dist import Distribution
from packaging.errors import (UnknownFileError, CompileError, from packaging.errors import (UnknownFileError, CompileError,
PackagingPlatformError) PackagingPlatformError)
@ -11,7 +10,7 @@ from packaging.command.build_ext import build_ext
from packaging.compiler.extension import Extension from packaging.compiler.extension import Extension
from test.script_helper import assert_python_ok from test.script_helper import assert_python_ok
from packaging.tests import support, unittest, verbose from packaging.tests import support, unittest
class BuildExtTestCase(support.TempdirManager, class BuildExtTestCase(support.TempdirManager,
@ -37,18 +36,10 @@ class BuildExtTestCase(support.TempdirManager,
support.fixup_build_ext(cmd) support.fixup_build_ext(cmd)
cmd.build_lib = self.tmp_dir cmd.build_lib = self.tmp_dir
cmd.build_temp = self.tmp_dir cmd.build_temp = self.tmp_dir
cmd.ensure_finalized()
cmd.run()
old_stdout = sys.stdout code = textwrap.dedent("""\
if not verbose:
# silence compiler output
sys.stdout = StringIO()
try:
cmd.ensure_finalized()
cmd.run()
finally:
sys.stdout = old_stdout
code = """if 1:
import sys import sys
sys.path.insert(0, %r) sys.path.insert(0, %r)
@ -63,7 +54,8 @@ class BuildExtTestCase(support.TempdirManager,
doc = 'This is a template module just for instruction.' doc = 'This is a template module just for instruction.'
assert xx.__doc__ == doc assert xx.__doc__ == doc
assert isinstance(xx.Null(), xx.Null) assert isinstance(xx.Null(), xx.Null)
assert isinstance(xx.Str(), xx.Str)""" assert isinstance(xx.Str(), xx.Str)
""")
code = code % self.tmp_dir code = code % self.tmp_dir
assert_python_ok('-c', code) assert_python_ok('-c', code)
@ -388,16 +380,8 @@ class BuildExtTestCase(support.TempdirManager,
cmd.build_temp = self.tmp_dir cmd.build_temp = self.tmp_dir
try: try:
old_stdout = sys.stdout cmd.ensure_finalized()
if not verbose: cmd.run()
# silence compiler output
sys.stdout = StringIO()
try:
cmd.ensure_finalized()
cmd.run()
finally:
sys.stdout = old_stdout
except CompileError: except CompileError:
self.fail("Wrong deployment target during compilation") self.fail("Wrong deployment target during compilation")

View file

@ -67,8 +67,6 @@ class BuildPyTestCase(support.TempdirManager,
def test_empty_package_dir(self): def test_empty_package_dir(self):
# See SF 1668596/1720897. # See SF 1668596/1720897.
cwd = os.getcwd()
# create the distribution files. # create the distribution files.
sources = self.mkdtemp() sources = self.mkdtemp()
pkg = os.path.join(sources, 'pkg') pkg = os.path.join(sources, 'pkg')
@ -79,24 +77,16 @@ class BuildPyTestCase(support.TempdirManager,
open(os.path.join(testdir, "testfile"), "wb").close() open(os.path.join(testdir, "testfile"), "wb").close()
os.chdir(sources) os.chdir(sources)
old_stdout = sys.stdout dist = Distribution({"packages": ["pkg"],
#sys.stdout = StringIO.StringIO() "package_dir": sources,
"package_data": {"pkg": ["doc/*"]}})
dist.script_args = ["build"]
dist.parse_command_line()
try: try:
dist = Distribution({"packages": ["pkg"], dist.run_commands()
"package_dir": sources, except PackagingFileError:
"package_data": {"pkg": ["doc/*"]}}) self.fail("failed package_data test when package_dir is ''")
dist.script_args = ["build"]
dist.parse_command_line()
try:
dist.run_commands()
except PackagingFileError:
self.fail("failed package_data test when package_dir is ''")
finally:
# Restore state.
os.chdir(cwd)
sys.stdout = old_stdout
def test_byte_compile(self): def test_byte_compile(self):
project_dir, dist = self.create_dist(py_modules=['boiledeggs']) project_dir, dist = self.create_dist(py_modules=['boiledeggs'])

View file

@ -36,8 +36,6 @@ class cleanTestCase(support.TempdirManager, support.LoggingCatcher,
'%r was not removed' % path) '%r was not removed' % path)
# let's run the command again (should spit warnings but succeed) # let's run the command again (should spit warnings but succeed)
cmd.all = True
cmd.ensure_finalized()
cmd.run() cmd.run()

View file

@ -62,6 +62,7 @@ class InstallDataTestCase(support.TempdirManager,
# let's try with warn_dir one # let's try with warn_dir one
cmd.warn_dir = True cmd.warn_dir = True
cmd.finalized = False
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()
@ -80,6 +81,7 @@ class InstallDataTestCase(support.TempdirManager,
cmd.data_files = {one: '{inst}/one', two: '{inst2}/two', cmd.data_files = {one: '{inst}/one', two: '{inst2}/two',
three: '{inst3}/three'} three: '{inst3}/three'}
cmd.finalized = False
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()

View file

@ -49,7 +49,7 @@ class InstallDistinfoTestCase(support.TempdirManager,
cmd = install_distinfo(dist) cmd = install_distinfo(dist)
dist.command_obj['install_distinfo'] = cmd dist.command_obj['install_distinfo'] = cmd
cmd.distinfo_dir = install_dir cmd.install_dir = install_dir
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()
@ -76,7 +76,7 @@ class InstallDistinfoTestCase(support.TempdirManager,
cmd = install_distinfo(dist) cmd = install_distinfo(dist)
dist.command_obj['install_distinfo'] = cmd dist.command_obj['install_distinfo'] = cmd
cmd.distinfo_dir = install_dir cmd.install_dir = install_dir
cmd.installer = 'bacon-python' cmd.installer = 'bacon-python'
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()
@ -96,7 +96,7 @@ class InstallDistinfoTestCase(support.TempdirManager,
cmd = install_distinfo(dist) cmd = install_distinfo(dist)
dist.command_obj['install_distinfo'] = cmd dist.command_obj['install_distinfo'] = cmd
cmd.distinfo_dir = install_dir cmd.install_dir = install_dir
cmd.requested = False cmd.requested = False
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()
@ -116,7 +116,7 @@ class InstallDistinfoTestCase(support.TempdirManager,
cmd = install_distinfo(dist) cmd = install_distinfo(dist)
dist.command_obj['install_distinfo'] = cmd dist.command_obj['install_distinfo'] = cmd
cmd.distinfo_dir = install_dir cmd.install_dir = install_dir
cmd.no_record = True cmd.no_record = True
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()
@ -214,7 +214,7 @@ class InstallDistinfoTestCase(support.TempdirManager,
cmd = install_distinfo(dist) cmd = install_distinfo(dist)
dist.command_obj['install_distinfo'] = cmd dist.command_obj['install_distinfo'] = cmd
cmd.distinfo_dir = install_dir cmd.install_dir = install_dir
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()

View file

@ -12,6 +12,7 @@ except ImportError:
DOCUTILS_SUPPORT = False DOCUTILS_SUPPORT = False
from packaging.tests import unittest, support from packaging.tests import unittest, support
from packaging.tests.support import Inputs
from packaging.command import register as register_module from packaging.command import register as register_module
from packaging.command.register import register from packaging.command.register import register
from packaging.errors import PackagingSetupError from packaging.errors import PackagingSetupError
@ -38,19 +39,6 @@ password:password
""" """
class Inputs:
"""Fakes user inputs."""
def __init__(self, *answers):
self.answers = answers
self.index = 0
def __call__(self, prompt=''):
try:
return self.answers[self.index]
finally:
self.index += 1
class FakeOpener: class FakeOpener:
"""Fakes a PyPI server""" """Fakes a PyPI server"""
def __init__(self): def __init__(self):
@ -143,6 +131,7 @@ class RegisterTestCase(support.TempdirManager,
register_module.input = _no_way register_module.input = _no_way
cmd.show_response = True cmd.show_response = True
cmd.finalized = False
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()

View file

@ -140,7 +140,7 @@ class SDistTestCase(support.TempdirManager,
# now trying a tar then a gztar # now trying a tar then a gztar
cmd.formats = ['tar', 'gztar'] cmd.formats = ['tar', 'gztar']
cmd.finalized = False
cmd.ensure_finalized() cmd.ensure_finalized()
cmd.run() cmd.run()

View file

@ -1,7 +1,6 @@
"""Tests for packaging.config.""" """Tests for packaging.config."""
import os import os
import sys import sys
from io import StringIO
from packaging import command from packaging import command
from packaging.dist import Distribution from packaging.dist import Distribution
@ -183,13 +182,14 @@ class FooBarBazTest:
def __init__(self, dist): def __init__(self, dist):
self.distribution = dist self.distribution = dist
self._record = []
@classmethod @classmethod
def get_command_name(cls): def get_command_name(cls):
return 'foo' return 'foo'
def run(self): def run(self):
self.distribution.foo_was_here = True self._record.append('foo has run')
def nothing(self): def nothing(self):
pass pass
@ -209,21 +209,11 @@ class ConfigTestCase(support.TempdirManager,
def setUp(self): def setUp(self):
super(ConfigTestCase, self).setUp() super(ConfigTestCase, self).setUp()
self.addCleanup(setattr, sys, 'stdout', sys.stdout)
self.addCleanup(setattr, sys, 'stderr', sys.stderr)
sys.stdout = StringIO()
sys.stderr = StringIO()
self.addCleanup(os.chdir, os.getcwd())
tempdir = self.mkdtemp() tempdir = self.mkdtemp()
self.working_dir = os.getcwd() self.working_dir = os.getcwd()
os.chdir(tempdir) os.chdir(tempdir)
self.tempdir = tempdir self.tempdir = tempdir
def tearDown(self):
os.chdir(self.working_dir)
super(ConfigTestCase, self).tearDown()
def write_setup(self, kwargs=None): def write_setup(self, kwargs=None):
opts = {'description-file': 'README', 'extra-files': '', opts = {'description-file': 'README', 'extra-files': '',
'setup-hooks': 'packaging.tests.test_config.version_hook'} 'setup-hooks': 'packaging.tests.test_config.version_hook'}
@ -378,7 +368,7 @@ class ConfigTestCase(support.TempdirManager,
self.assertIn('hooks', sys.modules) self.assertIn('hooks', sys.modules)
def test_missing_setup_hook_warns(self): def test_missing_setup_hook_warns(self):
self.write_setup({'setup-hooks': 'this.does._not.exist'}) self.write_setup({'setup-hooks': 'does._not.exist'})
self.write_file('README', 'yeah') self.write_file('README', 'yeah')
self.get_dist() self.get_dist()
logs = self.get_logs() logs = self.get_logs()
@ -491,10 +481,12 @@ class ConfigTestCase(support.TempdirManager,
self.write_file((pkg, '__init__.py'), '#') self.write_file((pkg, '__init__.py'), '#')
# try to run the install command to see if foo is called # try to run the install command to see if foo is called
self.addCleanup(command._COMMANDS.__delitem__, 'foo')
dist = self.get_dist() dist = self.get_dist()
self.assertIn('foo', command.get_command_names()) dist.run_command('install_dist')
self.assertEqual('FooBarBazTest', cmd = dist.get_command_obj('foo')
dist.get_command_obj('foo').__class__.__name__) self.assertEqual(cmd.__class__.__name__, 'FooBarBazTest')
self.assertEqual(cmd._record, ['foo has run'])
def test_suite(): def test_suite():

View file

@ -2,15 +2,17 @@
import os import os
import sys import sys
import sysconfig import sysconfig
from io import StringIO
from textwrap import dedent from textwrap import dedent
from packaging import create
from packaging.create import MainProgram, ask_yn, ask, main from packaging.create import MainProgram, ask_yn, ask, main
from packaging.tests import support, unittest from packaging.tests import support, unittest
from packaging.tests.support import Inputs
class CreateTestCase(support.TempdirManager, class CreateTestCase(support.TempdirManager,
support.EnvironRestorer, support.EnvironRestorer,
support.LoggingCatcher,
unittest.TestCase): unittest.TestCase):
maxDiff = None maxDiff = None
@ -18,11 +20,6 @@ class CreateTestCase(support.TempdirManager,
def setUp(self): def setUp(self):
super(CreateTestCase, self).setUp() super(CreateTestCase, self).setUp()
self._stdin = sys.stdin # TODO use Inputs
self._stdout = sys.stdout
sys.stdin = StringIO()
sys.stdout = StringIO()
self._cwd = os.getcwd()
self.wdir = self.mkdtemp() self.wdir = self.mkdtemp()
os.chdir(self.wdir) os.chdir(self.wdir)
# patch sysconfig # patch sysconfig
@ -32,29 +29,24 @@ class CreateTestCase(support.TempdirManager,
'doc': sys.prefix + '/share/doc/pyxfoil', } 'doc': sys.prefix + '/share/doc/pyxfoil', }
def tearDown(self): def tearDown(self):
sys.stdin = self._stdin
sys.stdout = self._stdout
os.chdir(self._cwd)
sysconfig.get_paths = self._old_get_paths sysconfig.get_paths = self._old_get_paths
if hasattr(create, 'input'):
del create.input
super(CreateTestCase, self).tearDown() super(CreateTestCase, self).tearDown()
def test_ask_yn(self): def test_ask_yn(self):
sys.stdin.write('y\n') create.input = Inputs('y')
sys.stdin.seek(0)
self.assertEqual('y', ask_yn('is this a test')) self.assertEqual('y', ask_yn('is this a test'))
def test_ask(self): def test_ask(self):
sys.stdin.write('a\n') create.input = Inputs('a', 'b')
sys.stdin.write('b\n')
sys.stdin.seek(0)
self.assertEqual('a', ask('is this a test')) self.assertEqual('a', ask('is this a test'))
self.assertEqual('b', ask(str(list(range(0, 70))), default='c', self.assertEqual('b', ask(str(list(range(0, 70))), default='c',
lengthy=True)) lengthy=True))
def test_set_multi(self): def test_set_multi(self):
mainprogram = MainProgram() mainprogram = MainProgram()
sys.stdin.write('aaaaa\n') create.input = Inputs('aaaaa')
sys.stdin.seek(0)
mainprogram.data['author'] = [] mainprogram.data['author'] = []
mainprogram._set_multi('_set_multi test', 'author') mainprogram._set_multi('_set_multi test', 'author')
self.assertEqual(['aaaaa'], mainprogram.data['author']) self.assertEqual(['aaaaa'], mainprogram.data['author'])
@ -130,8 +122,7 @@ class CreateTestCase(support.TempdirManager,
scripts=['my_script', 'bin/run'], scripts=['my_script', 'bin/run'],
) )
"""), encoding='utf-8') """), encoding='utf-8')
sys.stdin.write('y\n') create.input = Inputs('y')
sys.stdin.seek(0)
main() main()
path = os.path.join(self.wdir, 'setup.cfg') path = os.path.join(self.wdir, 'setup.cfg')
@ -206,9 +197,7 @@ My super Death-scription
barbar is now in the public domain, barbar is now in the public domain,
ho, baby! ho, baby!
''')) '''))
sys.stdin.write('y\n') create.input = Inputs('y')
sys.stdin.seek(0)
# FIXME Out of memory error.
main() main()
path = os.path.join(self.wdir, 'setup.cfg') path = os.path.join(self.wdir, 'setup.cfg')

View file

@ -6,30 +6,32 @@ import textwrap
import packaging.dist import packaging.dist
from packaging.dist import Distribution from packaging.dist import Distribution
from packaging.command import set_command, _COMMANDS
from packaging.command.cmd import Command from packaging.command.cmd import Command
from packaging.errors import PackagingModuleError, PackagingOptionError from packaging.errors import PackagingModuleError, PackagingOptionError
from packaging.tests import captured_stdout from packaging.tests import captured_stdout
from packaging.tests import support, unittest from packaging.tests import support, unittest
from packaging.tests.support import create_distribution from packaging.tests.support import create_distribution, use_command
from test.support import unload from test.support import unload
class test_dist(Command): class test_dist(Command):
"""Sample packaging extension command.""" """Custom command used for testing."""
user_options = [ user_options = [
("sample-option=", "S", "help text"), ('sample-option=', 'S',
"help text"),
] ]
def initialize_options(self): def initialize_options(self):
self.sample_option = None self.sample_option = None
self._record = []
def finalize_options(self): def finalize_options(self):
pass if self.sample_option is None:
self.sample_option = 'default value'
def run(self): def run(self):
pass self._record.append('test_dist has run')
class DistributionTestCase(support.TempdirManager, class DistributionTestCase(support.TempdirManager,
@ -45,14 +47,10 @@ class DistributionTestCase(support.TempdirManager,
# (defaulting to sys.argv) # (defaulting to sys.argv)
self.argv = sys.argv, sys.argv[:] self.argv = sys.argv, sys.argv[:]
del sys.argv[1:] del sys.argv[1:]
self._commands = _COMMANDS.copy()
def tearDown(self): def tearDown(self):
sys.argv = self.argv[0] sys.argv = self.argv[0]
sys.argv[:] = self.argv[1] sys.argv[:] = self.argv[1]
# XXX maybe we need a public API to remove commands
_COMMANDS.clear()
_COMMANDS.update(self._commands)
super(DistributionTestCase, self).tearDown() super(DistributionTestCase, self).tearDown()
@unittest.skip('needs to be updated') @unittest.skip('needs to be updated')
@ -181,7 +179,8 @@ class DistributionTestCase(support.TempdirManager,
self.write_file((temp_home, "config2.cfg"), self.write_file((temp_home, "config2.cfg"),
'[test_dist]\npre-hook.b = type') '[test_dist]\npre-hook.b = type')
set_command('packaging.tests.test_dist.test_dist') use_command(self, 'packaging.tests.test_dist.test_dist')
dist = create_distribution(config_files) dist = create_distribution(config_files)
cmd = dist.get_command_obj("test_dist") cmd = dist.get_command_obj("test_dist")
self.assertEqual(cmd.pre_hook, {"a": 'type', "b": 'type'}) self.assertEqual(cmd.pre_hook, {"a": 'type', "b": 'type'})
@ -209,7 +208,7 @@ class DistributionTestCase(support.TempdirManager,
record.append('post-%s' % cmd.get_command_name()) record.append('post-%s' % cmd.get_command_name())
''')) '''))
set_command('packaging.tests.test_dist.test_dist') use_command(self, 'packaging.tests.test_dist.test_dist')
d = create_distribution([config_file]) d = create_distribution([config_file])
cmd = d.get_command_obj("test_dist") cmd = d.get_command_obj("test_dist")
@ -236,7 +235,7 @@ class DistributionTestCase(support.TempdirManager,
[test_dist] [test_dist]
pre-hook.test = nonexistent.dotted.name''')) pre-hook.test = nonexistent.dotted.name'''))
set_command('packaging.tests.test_dist.test_dist') use_command(self, 'packaging.tests.test_dist.test_dist')
d = create_distribution([config_file]) d = create_distribution([config_file])
cmd = d.get_command_obj("test_dist") cmd = d.get_command_obj("test_dist")
cmd.ensure_finalized() cmd.ensure_finalized()
@ -251,7 +250,7 @@ class DistributionTestCase(support.TempdirManager,
[test_dist] [test_dist]
pre-hook.test = packaging.tests.test_dist.__doc__''')) pre-hook.test = packaging.tests.test_dist.__doc__'''))
set_command('packaging.tests.test_dist.test_dist') use_command(self, 'packaging.tests.test_dist.test_dist')
d = create_distribution([config_file]) d = create_distribution([config_file])
cmd = d.get_command_obj("test_dist") cmd = d.get_command_obj("test_dist")
cmd.ensure_finalized() cmd.ensure_finalized()

View file

@ -33,11 +33,9 @@ class RunTestCase(support.TempdirManager,
def setUp(self): def setUp(self):
super(RunTestCase, self).setUp() super(RunTestCase, self).setUp()
self.old_stdout = sys.stdout
self.old_argv = sys.argv, sys.argv[:] self.old_argv = sys.argv, sys.argv[:]
def tearDown(self): def tearDown(self):
sys.stdout = self.old_stdout
sys.argv = self.old_argv[0] sys.argv = self.old_argv[0]
sys.argv[:] = self.old_argv[1] sys.argv[:] = self.old_argv[1]
super(RunTestCase, self).tearDown() super(RunTestCase, self).tearDown()

View file

@ -1,6 +1,5 @@
"""Tests for the packaging.uninstall module.""" """Tests for the packaging.uninstall module."""
import os import os
import sys
import logging import logging
import packaging.util import packaging.util
@ -31,16 +30,12 @@ class UninstallTestCase(support.TempdirManager,
def setUp(self): def setUp(self):
super(UninstallTestCase, self).setUp() super(UninstallTestCase, self).setUp()
self.addCleanup(setattr, sys, 'stdout', sys.stdout)
self.addCleanup(setattr, sys, 'stderr', sys.stderr)
self.addCleanup(os.chdir, os.getcwd())
self.addCleanup(enable_cache) self.addCleanup(enable_cache)
self.root_dir = self.mkdtemp() self.root_dir = self.mkdtemp()
self.cwd = os.getcwd() self.cwd = os.getcwd()
disable_cache() disable_cache()
def tearDown(self): def tearDown(self):
os.chdir(self.cwd)
packaging.util._path_created.clear() packaging.util._path_created.clear()
super(UninstallTestCase, self).tearDown() super(UninstallTestCase, self).tearDown()

View file

@ -170,8 +170,8 @@ class UtilTestCase(support.EnvironRestorer,
def unmock_popen(self): def unmock_popen(self):
util.find_executable = self.old_find_executable util.find_executable = self.old_find_executable
subprocess.Popen = self.old_popen subprocess.Popen = self.old_popen
sys.old_stdout = self.old_stdout sys.stdout = self.old_stdout
sys.old_stderr = self.old_stderr sys.stderr = self.old_stderr
def test_convert_path(self): def test_convert_path(self):
# linux/mac # linux/mac

View file

@ -488,8 +488,7 @@ def get_config_vars(*args):
# Setting 'userbase' is done below the call to the # Setting 'userbase' is done below the call to the
# init function to enable using 'get_config_var' in # init function to enable using 'get_config_var' in
# the init-function. # the init-function.
if sys.version >= '2.6': _CONFIG_VARS['userbase'] = _getuserbase()
_CONFIG_VARS['userbase'] = _getuserbase()
if 'srcdir' not in _CONFIG_VARS: if 'srcdir' not in _CONFIG_VARS:
_CONFIG_VARS['srcdir'] = _PROJECT_BASE _CONFIG_VARS['srcdir'] = _PROJECT_BASE

View file

@ -172,6 +172,7 @@ import io
import json import json
import logging import logging
import os import os
import packaging.command
import packaging.database import packaging.database
import platform import platform
import random import random
@ -967,7 +968,7 @@ class saved_test_environment:
'sys.warnoptions', 'threading._dangling', 'sys.warnoptions', 'threading._dangling',
'multiprocessing.process._dangling', 'multiprocessing.process._dangling',
'sysconfig._CONFIG_VARS', 'sysconfig._SCHEMES', 'sysconfig._CONFIG_VARS', 'sysconfig._SCHEMES',
'packaging.database_caches', 'packaging.command._COMMANDS', 'packaging.database_caches',
) )
def get_sys_argv(self): def get_sys_argv(self):
@ -1055,6 +1056,22 @@ class saved_test_environment:
# Can't easily revert the logging state # Can't easily revert the logging state
pass pass
def get_packaging_command__COMMANDS(self):
# registry mapping command names to full dotted path or to the actual
# class (resolved on demand); this check only looks at the names, not
# the types of the values (IOW, if a value changes from a string
# (dotted path) to a class it's okay but if a key (i.e. command class)
# is added we complain)
id_ = id(packaging.command._COMMANDS)
keys = set(packaging.command._COMMANDS)
return id_, keys
def restore_packaging_command__COMMANDS(self, saved):
# if command._COMMANDS was bound to another dict obhect, we can't
# restore the previous object and contents, because the get_ method
# above does not return the dict object (to ignore changes in values)
for key in packaging.command._COMMANDS.keys() - saved[1]:
del packaging.command._COMMANDS[key]
def get_packaging_database_caches(self): def get_packaging_database_caches(self):
# caching system used by the PEP 376 implementation # caching system used by the PEP 376 implementation
# we have one boolean and four dictionaries, initially empty # we have one boolean and four dictionaries, initially empty

View file

@ -7,8 +7,7 @@ import sys
import re import re
import fileinput import fileinput
import collections import collections
import types import builtins
import codecs
import unittest import unittest
try: try:
@ -807,18 +806,8 @@ class Test_hook_compressed(unittest.TestCase):
@staticmethod @staticmethod
def replace_builtin_open(new_open_func): def replace_builtin_open(new_open_func):
builtins_type = type(__builtins__) original_open = builtins.open
if builtins_type is dict: builtins.open = new_open_func
original_open = __builtins__["open"]
__builtins__["open"] = new_open_func
elif builtins_type is types.ModuleType:
original_open = __builtins__.open
__builtins__.open = new_open_func
else:
raise RuntimeError(
"unknown __builtins__ type: %r (unable to replace open)" %
builtins_type)
return original_open return original_open
class Test_hook_encoded(unittest.TestCase): class Test_hook_encoded(unittest.TestCase):
@ -829,21 +818,22 @@ class Test_hook_encoded(unittest.TestCase):
result = fileinput.hook_encoded(encoding) result = fileinput.hook_encoded(encoding)
fake_open = InvocationRecorder() fake_open = InvocationRecorder()
original_open = codecs.open original_open = builtins.open
codecs.open = fake_open builtins.open = fake_open
try: try:
filename = object() filename = object()
mode = object() mode = object()
open_result = result(filename, mode) open_result = result(filename, mode)
finally: finally:
codecs.open = original_open builtins.open = original_open
self.assertEqual(fake_open.invocation_count, 1) self.assertEqual(fake_open.invocation_count, 1)
args = fake_open.last_invocation[0] args, kwargs = fake_open.last_invocation
self.assertIs(args[0], filename) self.assertIs(args[0], filename)
self.assertIs(args[1], mode) self.assertIs(args[1], mode)
self.assertIs(args[2], encoding) self.assertIs(kwargs.pop('encoding'), encoding)
self.assertFalse(kwargs)
def test_main(): def test_main():
run_unittest( run_unittest(

View file

@ -49,6 +49,7 @@ import weakref
try: try:
import threading import threading
# The following imports are needed only for tests which # The following imports are needed only for tests which
# require threading
import asynchat import asynchat
import asyncore import asyncore
import errno import errno
@ -95,9 +96,7 @@ class BaseTest(unittest.TestCase):
finally: finally:
logging._releaseLock() logging._releaseLock()
# Set two unused loggers: one non-ASCII and one Unicode. # Set two unused loggers
# This is to test correct operation when sorting existing
# loggers in the configuration code. See issue 8201.
self.logger1 = logging.getLogger("\xab\xd7\xbb") self.logger1 = logging.getLogger("\xab\xd7\xbb")
self.logger2 = logging.getLogger("\u013f\u00d6\u0047") self.logger2 = logging.getLogger("\u013f\u00d6\u0047")
@ -310,8 +309,6 @@ class BuiltinLevelsTest(BaseTest):
('INF.BADPARENT', 'INFO', '4'), ('INF.BADPARENT', 'INFO', '4'),
]) ])
def test_invalid_name(self):
self.assertRaises(TypeError, logging.getLogger, any)
class BasicFilterTest(BaseTest): class BasicFilterTest(BaseTest):
@ -3514,6 +3511,22 @@ class LoggerTest(BaseTest):
self.addCleanup(setattr, self.logger.manager, 'disable', old_disable) self.addCleanup(setattr, self.logger.manager, 'disable', old_disable)
self.assertFalse(self.logger.isEnabledFor(22)) self.assertFalse(self.logger.isEnabledFor(22))
def test_root_logger_aliases(self):
root = logging.getLogger()
self.assertIs(root, logging.root)
self.assertIs(root, logging.getLogger(None))
self.assertIs(root, logging.getLogger(''))
self.assertIs(root, logging.getLogger('foo').root)
self.assertIs(root, logging.getLogger('foo.bar').root)
self.assertIs(root, logging.getLogger('foo').parent)
self.assertIsNot(root, logging.getLogger('\0'))
self.assertIsNot(root, logging.getLogger('foo.bar').parent)
def test_invalid_names(self):
self.assertRaises(TypeError, logging.getLogger, any)
self.assertRaises(TypeError, logging.getLogger, b'foo')
class BaseFileTest(BaseTest): class BaseFileTest(BaseTest):
"Base class for handler tests that write log files" "Base class for handler tests that write log files"

View file

@ -56,16 +56,20 @@ class TestUnicodeFiles(unittest.TestCase):
# Should be able to rename the file using either name. # Should be able to rename the file using either name.
self.assertTrue(os.path.isfile(filename1)) # must exist. self.assertTrue(os.path.isfile(filename1)) # must exist.
os.rename(filename1, filename2 + ".new") os.rename(filename1, filename2 + ".new")
self.assertTrue(os.path.isfile(filename1+".new")) self.assertFalse(os.path.isfile(filename2))
self.assertTrue(os.path.isfile(filename1 + '.new'))
os.rename(filename1 + ".new", filename2) os.rename(filename1 + ".new", filename2)
self.assertFalse(os.path.isfile(filename1 + '.new'))
self.assertTrue(os.path.isfile(filename2)) self.assertTrue(os.path.isfile(filename2))
shutil.copy(filename1, filename2 + ".new") shutil.copy(filename1, filename2 + ".new")
os.unlink(filename1 + ".new") # remove using equiv name. os.unlink(filename1 + ".new") # remove using equiv name.
# And a couple of moves, one using each name. # And a couple of moves, one using each name.
shutil.move(filename1, filename2 + ".new") shutil.move(filename1, filename2 + ".new")
self.assertTrue(not os.path.exists(filename2)) self.assertFalse(os.path.exists(filename2))
self.assertTrue(os.path.exists(filename1 + '.new'))
shutil.move(filename1 + ".new", filename2) shutil.move(filename1 + ".new", filename2)
self.assertFalse(os.path.exists(filename2 + '.new'))
self.assertTrue(os.path.exists(filename1)) self.assertTrue(os.path.exists(filename1))
# Note - due to the implementation of shutil.move, # Note - due to the implementation of shutil.move,
# it tries a rename first. This only fails on Windows when on # it tries a rename first. This only fails on Windows when on
@ -73,7 +77,9 @@ class TestUnicodeFiles(unittest.TestCase):
# So we test the shutil.copy2 function, which is the thing most # So we test the shutil.copy2 function, which is the thing most
# likely to fail. # likely to fail.
shutil.copy2(filename1, filename2 + ".new") shutil.copy2(filename1, filename2 + ".new")
self.assertTrue(os.path.isfile(filename1 + '.new'))
os.unlink(filename1 + ".new") os.unlink(filename1 + ".new")
self.assertFalse(os.path.exists(filename2 + '.new'))
def _do_directory(self, make_name, chdir_name): def _do_directory(self, make_name, chdir_name):
cwd = os.getcwdb() cwd = os.getcwdb()

View file

@ -294,8 +294,6 @@ Core and Builtins
- Issue #11320: fix bogus memory management in Modules/getpath.c, leading to - Issue #11320: fix bogus memory management in Modules/getpath.c, leading to
a possible crash when calling Py_SetPath(). a possible crash when calling Py_SetPath().
- _ast.__version__ is now a Mercurial hex revision.
- Issue #11432: A bug was introduced in subprocess.Popen on posix systems with - Issue #11432: A bug was introduced in subprocess.Popen on posix systems with
3.2.0 where the stdout or stderr file descriptor being the same as the stdin 3.2.0 where the stdout or stderr file descriptor being the same as the stdin
file descriptor would raise an exception. webbrowser.open would fail. fixed. file descriptor would raise an exception. webbrowser.open would fail. fixed.
@ -1555,8 +1553,6 @@ Extension Modules
signature. Without this, architectures where sizeof void* != sizeof int are signature. Without this, architectures where sizeof void* != sizeof int are
broken. Patch given by Hallvard B Furuseth. broken. Patch given by Hallvard B Furuseth.
- Issue #12221: Replace pyexpat.__version__ with the Python version.
- Issue #12051: Fix segfault in json.dumps() while encoding highly-nested - Issue #12051: Fix segfault in json.dumps() while encoding highly-nested
objects using the C accelerations. objects using the C accelerations.