Kaydet (Commit) fad46e19 authored tarafından Éric Araujo's avatar Éric Araujo

Clean up mocking of stdout and stdin in packaging tests.

Running with regrtest does not show spurious output or unrestored
sys.std* objects; sometimes running with make test is different, I’ll
watch the buildbots.

In addition, update the create module to use logging.
üst 261ccdce
...@@ -30,6 +30,7 @@ from textwrap import dedent ...@@ -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): ...@@ -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, ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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():
......
...@@ -52,7 +52,7 @@ __all__ = [ ...@@ -52,7 +52,7 @@ __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', 'use_command', 'fake_dec', 'create_distribution', 'use_command',
'copy_xxmodule_c', 'fixup_build_ext', 'copy_xxmodule_c', 'fixup_build_ext',
...@@ -274,6 +274,22 @@ class TestDistribution(Distribution): ...@@ -274,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()
......
...@@ -3,7 +3,6 @@ import sys ...@@ -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 ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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")
......
...@@ -67,8 +67,6 @@ class BuildPyTestCase(support.TempdirManager, ...@@ -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, ...@@ -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'])
......
...@@ -12,6 +12,7 @@ except ImportError: ...@@ -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 ...@@ -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):
......
"""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
...@@ -210,21 +209,11 @@ class ConfigTestCase(support.TempdirManager, ...@@ -210,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'}
...@@ -379,7 +368,7 @@ class ConfigTestCase(support.TempdirManager, ...@@ -379,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()
......
...@@ -2,15 +2,17 @@ ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 ...@@ -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')
......
...@@ -33,11 +33,9 @@ class RunTestCase(support.TempdirManager, ...@@ -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()
......
"""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, ...@@ -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()
......
...@@ -170,8 +170,8 @@ class UtilTestCase(support.EnvironRestorer, ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment