Commit 3bb8be6d authored by Éric Araujo's avatar Éric Araujo

Branch merge

parents 1a129c88 784cd4cc
No related merge requests found
......@@ -19,6 +19,8 @@ information that's already documented for Python in the
:local:
.. _setupcfg-syntax:
Syntax
======
......@@ -117,6 +119,8 @@ from most specialized to most common.
file**. This will be useful to let users publish a single file.
.. _setupcfg-sections:
Description of sections and fields
==================================
......@@ -149,6 +153,8 @@ command sections
on the command line.
.. _setupcfg-section-global:
Global options
--------------
......@@ -194,6 +200,9 @@ setup_hooks
setup_hooks = _setuphooks.customize_config
.. _setupcfg-section-metadata:
Metadata
--------
......@@ -318,6 +327,8 @@ You should not give any explicit value for metadata-version: it will be guessed
from the fields present in the file.
.. _setupcfg-section-files:
Files
-----
......@@ -325,7 +336,8 @@ This section describes the files included in the project.
packages_root
the root directory containing all packages and modules
(default: current directory). *optional*
(default: current directory, i.e. the project's top-level
directory where :file:`setup.cfg` lives). *optional*
packages
a list of packages the project includes *optional*, *multi*
......@@ -337,8 +349,8 @@ scripts
a list of scripts the project includes *optional*, *multi*
extra_files
a list of patterns to include extra files *optional*,
*multi*
a list of patterns for additional files to include in source distributions
(see :ref:`packaging-manifest`) *optional*, *multi*
Example::
......@@ -747,8 +759,10 @@ We use brace expansion syntax to place all the shell and batch scripts into
{scripts} category.
Extension sections
------------------
.. _setupcfg-section-extensions:
Extension modules sections
--------------------------
If a project includes extension modules written in C or C++, each one of them
needs to have its options defined in a dedicated section. Here's an example::
......@@ -779,8 +793,10 @@ addition, multi-line values accept environment markers on each line, after a
``--``.
Command sections
----------------
.. _setupcfg-section-commands:
Commands sections
-----------------
To pass options to commands without having to type them on the command line
for each invocation, you can write them in the :file:`setup.cfg` file, in a
......@@ -803,6 +819,11 @@ section named after the command. Example::
Option values given in the configuration file can be overriden on the command
line. See :ref:`packaging-setup-config` for more information.
These sections are also used to define :ref:`command hooks
<packaging-command-hooks>`.
.. _setupcfg-extensibility:
Extensibility
=============
......@@ -817,6 +838,8 @@ An extension field starts with ``X-``. Example::
X-Debian-Name = python-distribute
.. _setupcfg-changes:
Changes in the specification
============================
......@@ -852,6 +875,8 @@ A tool written to produce 1.x should have these properties:
- May write optional fields.
.. _setupcfg-acks:
Acknowledgments
===============
......
"""Build pure Python modules (just copy to build directory)."""
import os
import imp
import sys
from glob import glob
......@@ -330,9 +331,10 @@ class build_py(Command, Mixin2to3):
outputs.append(filename)
if include_bytecode:
if self.compile:
outputs.append(filename + "c")
outputs.append(imp.cache_from_source(filename))
if self.optimize > 0:
outputs.append(filename + "o")
outputs.append(imp.cache_from_source(filename,
debug_override=False))
outputs += [
os.path.join(build_dir, filename)
......
"""Install all modules (extensions and pure Python)."""
import os
import imp
import sys
import logging
......@@ -172,9 +173,10 @@ class install_lib(Command):
if ext != PYTHON_SOURCE_EXTENSION:
continue
if self.compile:
bytecode_files.append(py_file + "c")
bytecode_files.append(imp.cache_from_source(py_file))
if self.optimize > 0:
bytecode_files.append(py_file + "o")
bytecode_files.append(imp.cache_from_source(
py_file, debug_override=False))
return bytecode_files
......
......@@ -185,6 +185,7 @@ _MISSING = object()
_FILESAFE = re.compile('[^A-Za-z0-9.]+')
class Metadata:
"""The metadata of a release.
......@@ -228,10 +229,8 @@ class Metadata:
def __delitem__(self, name):
field_name = self._convert_name(name)
try:
del self._fields[field_name]
except KeyError:
raise KeyError(name)
# we let a KeyError propagate
del self._fields[field_name]
self._set_best_version()
def __contains__(self, name):
......
......@@ -3,7 +3,6 @@
# Ripped from importlib tests, thanks Brett!
import os
import sys
import unittest
from test.support import run_unittest, reap_children, reap_threads
......
......@@ -82,10 +82,13 @@ class LoggingCatcher:
configured to record all messages logged to the 'packaging' logger.
Use get_logs to retrieve messages and self.loghandler.flush to discard
them. get_logs automatically flushes the logs; if you test code that
generates logging messages but don't use get_logs, you have to flush
manually before doing other checks on logging message, otherwise you
will get irrelevant results. See example in test_command_check.
them. get_logs automatically flushes the logs, unless you pass
*flush=False*, for example to make multiple calls to the method with
different level arguments. If your test calls some code that generates
logging message and then you don't call get_logs, you will need to flush
manually before testing other code in the same test_* method, otherwise
get_logs in the next lines will see messages from the previous lines.
See example in test_command_check.
"""
def setUp(self):
......@@ -109,25 +112,23 @@ class LoggingCatcher:
logger2to3.setLevel(self._old_levels[1])
super(LoggingCatcher, self).tearDown()
def get_logs(self, *levels):
"""Return all log messages with level in *levels*.
def get_logs(self, level=logging.WARNING, flush=True):
"""Return all log messages with given level.
Without explicit levels given, returns all messages. *levels* defaults
to all levels. For log calls with arguments (i.e.
logger.info('bla bla %r', arg)), the messages will be formatted before
being returned (e.g. "bla bla 'thing'").
*level* defaults to logging.WARNING.
Returns a list. Automatically flushes the loghandler after being
called.
For log calls with arguments (i.e. logger.info('bla bla %r', arg)),
the messages will be formatted before being returned (e.g. "bla bla
'thing'").
Example: self.get_logs(logging.WARN, logging.DEBUG).
Returns a list. Automatically flushes the loghandler after being
called, unless *flush* is False (this is useful to get e.g. all
warnings then all info messages).
"""
if not levels:
messages = [log.getMessage() for log in self.loghandler.buffer]
else:
messages = [log.getMessage() for log in self.loghandler.buffer
if log.levelno in levels]
self.loghandler.flush()
messages = [log.getMessage() for log in self.loghandler.buffer
if log.levelno == level]
if flush:
self.loghandler.flush()
return messages
......
......@@ -102,6 +102,40 @@ class BuildPyTestCase(support.TempdirManager,
os.chdir(cwd)
sys.stdout = old_stdout
@unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
def test_byte_compile(self):
project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
os.chdir(project_dir)
self.write_file('boiledeggs.py', 'import antigravity')
cmd = build_py(dist)
cmd.compile = True
cmd.build_lib = 'here'
cmd.finalize_options()
cmd.run()
found = os.listdir(cmd.build_lib)
self.assertEqual(sorted(found), ['__pycache__', 'boiledeggs.py'])
found = os.listdir(os.path.join(cmd.build_lib, '__pycache__'))
self.assertEqual(found, ['boiledeggs.%s.pyc' % imp.get_tag()])
@unittest.skipIf(sys.dont_write_bytecode, 'byte-compile disabled')
def test_byte_compile_optimized(self):
project_dir, dist = self.create_dist(py_modules=['boiledeggs'])
os.chdir(project_dir)
self.write_file('boiledeggs.py', 'import antigravity')
cmd = build_py(dist)
cmd.compile = True
cmd.optimize = 1
cmd.build_lib = 'here'
cmd.finalize_options()
cmd.run()
found = os.listdir(cmd.build_lib)
self.assertEqual(sorted(found), ['__pycache__', 'boiledeggs.py'])
found = os.listdir(os.path.join(cmd.build_lib, '__pycache__'))
self.assertEqual(sorted(found), ['boiledeggs.%s.pyc' % imp.get_tag(),
'boiledeggs.%s.pyo' % imp.get_tag()])
def test_dont_write_bytecode(self):
# makes sure byte_compile is not used
pkg_dir, dist = self.create_dist()
......@@ -118,6 +152,7 @@ class BuildPyTestCase(support.TempdirManager,
self.assertIn('byte-compiling is disabled', self.get_logs()[0])
def test_suite():
return unittest.makeSuite(BuildPyTestCase)
......
"""Tests for distutils.command.check."""
import logging
from packaging.command.check import check
from packaging.metadata import _HAS_DOCUTILS
from packaging.errors import PackagingSetupError, MetadataMissingError
......@@ -27,11 +26,11 @@ class CheckTestCase(support.LoggingCatcher,
# let's run the command with no metadata at all
# by default, check is checking the metadata
# should have some warnings
cmd = self._run()
self._run()
# trick: using assertNotEqual with an empty list will give us a more
# useful error message than assertGreater(.., 0) when the code change
# and the test fails
self.assertNotEqual([], self.get_logs(logging.WARNING))
self.assertNotEqual(self.get_logs(), [])
# now let's add the required fields
# and run it again, to make sure we don't get
......@@ -40,8 +39,8 @@ class CheckTestCase(support.LoggingCatcher,
'author_email': 'xxx',
'name': 'xxx', 'version': '4.2',
}
cmd = self._run(metadata)
self.assertEqual([], self.get_logs(logging.WARNING))
self._run(metadata)
self.assertEqual(self.get_logs(), [])
# now with the strict mode, we should
# get an error if there are missing metadata
......@@ -53,8 +52,8 @@ class CheckTestCase(support.LoggingCatcher,
self.loghandler.flush()
# and of course, no error when all metadata fields are present
cmd = self._run(metadata, strict=True)
self.assertEqual([], self.get_logs(logging.WARNING))
self._run(metadata, strict=True)
self.assertEqual(self.get_logs(), [])
# now a test with non-ASCII characters
metadata = {'home_page': 'xxx', 'author': '\u00c9ric',
......@@ -62,15 +61,15 @@ class CheckTestCase(support.LoggingCatcher,
'version': '1.2',
'summary': 'Something about esszet \u00df',
'description': 'More things about esszet \u00df'}
cmd = self._run(metadata)
self.assertEqual([], self.get_logs(logging.WARNING))
self._run(metadata)
self.assertEqual(self.get_logs(), [])
def test_check_metadata_1_2(self):
# let's run the command with no metadata at all
# by default, check is checking the metadata
# should have some warnings
cmd = self._run()
self.assertNotEqual([], self.get_logs(logging.WARNING))
self._run()
self.assertNotEqual(self.get_logs(), [])
# now let's add the required fields and run it again, to make sure we
# don't get any warning anymore let's use requires_python as a marker
......@@ -80,8 +79,8 @@ class CheckTestCase(support.LoggingCatcher,
'name': 'xxx', 'version': '4.2',
'requires_python': '2.4',
}
cmd = self._run(metadata)
self.assertEqual([], self.get_logs(logging.WARNING))
self._run(metadata)
self.assertEqual(self.get_logs(), [])
# now with the strict mode, we should
# get an error if there are missing metadata
......@@ -99,8 +98,8 @@ class CheckTestCase(support.LoggingCatcher,
# now with correct version format again
metadata['version'] = '4.2'
cmd = self._run(metadata, strict=True)
self.assertEqual([], self.get_logs(logging.WARNING))
self._run(metadata, strict=True)
self.assertEqual(self.get_logs(), [])
@unittest.skipUnless(_HAS_DOCUTILS, "requires docutils")
def test_check_restructuredtext(self):
......@@ -109,9 +108,7 @@ class CheckTestCase(support.LoggingCatcher,
pkg_info, dist = self.create_dist(description=broken_rest)
cmd = check(dist)
cmd.check_restructuredtext()
self.assertEqual(len(self.get_logs(logging.WARNING)), 1)
# clear warnings from the previous call
self.loghandler.flush()
self.assertEqual(len(self.get_logs()), 1)
# let's see if we have an error with strict=1
metadata = {'home_page': 'xxx', 'author': 'xxx',
......@@ -126,7 +123,7 @@ class CheckTestCase(support.LoggingCatcher,
dist = self.create_dist(description='title\n=====\n\ntest \u00df')[1]
cmd = check(dist)
cmd.check_restructuredtext()
self.assertEqual([], self.get_logs(logging.WARNING))
self.assertEqual(self.get_logs(), [])
def test_check_all(self):
self.assertRaises(PackagingSetupError, self._run,
......@@ -143,18 +140,18 @@ class CheckTestCase(support.LoggingCatcher,
}
cmd = check(dist)
cmd.check_hooks_resolvable()
self.assertEqual(len(self.get_logs(logging.WARNING)), 1)
self.assertEqual(len(self.get_logs()), 1)
def test_warn(self):
_, dist = self.create_dist()
cmd = check(dist)
self.assertEqual([], self.get_logs())
self.assertEqual(self.get_logs(), [])
cmd.warn('hello')
self.assertEqual(['check: hello'], self.get_logs())
self.assertEqual(self.get_logs(), ['check: hello'])
cmd.warn('hello %s', 'world')
self.assertEqual(['check: hello world'], self.get_logs())
self.assertEqual(self.get_logs(), ['check: hello world'])
cmd.warn('hello %s %s', 'beautiful', 'world')
self.assertEqual(['check: hello beautiful world'], self.get_logs())
self.assertEqual(self.get_logs(), ['check: hello beautiful world'])
def test_suite():
......
......@@ -23,7 +23,7 @@ class cleanTestCase(support.TempdirManager, support.LoggingCatcher,
if name == 'build_base':
continue
for f in ('one', 'two', 'three'):
self.write_file(os.path.join(path, f))
self.write_file((path, f))
# let's run the command
cmd.all = True
......
"""Tests for distutils.cmd."""
import os
import logging
from packaging.command.cmd import Command
from packaging.dist import Distribution
......@@ -43,7 +44,7 @@ class CommandTestCase(support.LoggingCatcher,
wanted = ["command options for 'MyCmd':", ' option1 = 1',
' option2 = 1']
msgs = self.get_logs()
msgs = self.get_logs(logging.INFO)
self.assertEqual(msgs, wanted)
def test_ensure_string(self):
......
......@@ -117,6 +117,11 @@ class InstallDataTestCase(support.TempdirManager,
dist.command_obj['install_distinfo'] = cmd
cmd.run()
# first a few sanity checks
self.assertEqual(os.listdir(scripts_dir), ['spamd'])
self.assertEqual(os.listdir(install_dir), ['Spamlib-0.1.dist-info'])
# now the real test
fn = os.path.join(install_dir, 'Spamlib-0.1.dist-info', 'RESOURCES')
with open(fn, encoding='utf-8') as fp:
content = fp.read().strip()
......
"""Tests for packaging.command.install."""
import os
import imp
import sys
from sysconfig import (get_scheme_names, get_config_vars,
_SCHEMES, get_config_var, get_path)
......@@ -92,21 +93,20 @@ class InstallTestCase(support.TempdirManager,
self.old_expand = os.path.expanduser
os.path.expanduser = _expanduser
try:
# this is the actual test
self._test_user_site()
finally:
def cleanup():
_CONFIG_VARS['userbase'] = self.old_user_base
_SCHEMES.set(scheme, 'purelib', self.old_user_site)
os.path.expanduser = self.old_expand
def _test_user_site(self):
self.addCleanup(cleanup)
schemes = get_scheme_names()
for key in ('nt_user', 'posix_user', 'os2_home'):
self.assertIn(key, schemes)
dist = Distribution({'name': 'xx'})
cmd = install_dist(dist)
# making sure the user option is there
options = [name for name, short, lable in
cmd.user_options]
......@@ -181,9 +181,11 @@ class InstallTestCase(support.TempdirManager,
def test_old_record(self):
# test pre-PEP 376 --record option (outside dist-info dir)
install_dir = self.mkdtemp()
project_dir, dist = self.create_dist(scripts=['hello'])
project_dir, dist = self.create_dist(py_modules=['hello'],
scripts=['sayhi'])
os.chdir(project_dir)
self.write_file('hello', "print('o hai')")
self.write_file('hello.py', "def main(): print('o hai')")
self.write_file('sayhi', 'from hello import main; main()')
cmd = install_dist(dist)
dist.command_obj['install_dist'] = cmd
......@@ -196,8 +198,9 @@ class InstallTestCase(support.TempdirManager,
content = f.read()
found = [os.path.basename(line) for line in content.splitlines()]
expected = ['hello', 'METADATA', 'INSTALLER', 'REQUESTED', 'RECORD']
self.assertEqual(found, expected)
expected = ['hello.py', 'hello.%s.pyc' % imp.get_tag(), 'sayhi',
'METADATA', 'INSTALLER', 'REQUESTED', 'RECORD']
self.assertEqual(sorted(found), sorted(expected))
# XXX test that fancy_getopt is okay with options named
# record and no-record but unrelated
......
......@@ -2,7 +2,6 @@
import os
import zipfile
import tarfile
import logging
from packaging.tests.support import requires_zlib
......@@ -221,7 +220,7 @@ class SDistTestCase(support.TempdirManager,
# with the check subcommand
cmd.ensure_finalized()
cmd.run()
warnings = self.get_logs(logging.WARN)
warnings = self.get_logs()
self.assertEqual(len(warnings), 4)
# trying with a complete set of metadata
......@@ -230,13 +229,10 @@ class SDistTestCase(support.TempdirManager,
cmd.ensure_finalized()
cmd.metadata_check = False
cmd.run()
warnings = self.get_logs(logging.WARN)
# removing manifest generated warnings
warnings = [warn for warn in warnings if
not warn.endswith('-- skipping')]
# the remaining warnings are about the use of the default file list and
# the absence of setup.cfg
warnings = self.get_logs()
self.assertEqual(len(warnings), 2)
self.assertIn('using default file list', warnings[0])
self.assertIn("'setup.cfg' file not found", warnings[1])
def test_show_formats(self):
__, stdout = captured_stdout(show_formats)
......
......@@ -2,7 +2,6 @@ import os
import re
import sys
import shutil
import logging
import unittest as ut1
import packaging.database
......@@ -140,7 +139,8 @@ class TestTest(TempdirManager,
cmd.run()
self.assertEqual(['build has run'], record)
def _test_works_with_2to3(self):
@unittest.skip('needs to be written')
def test_works_with_2to3(self):
pass
def test_checks_requires(self):
......@@ -149,7 +149,7 @@ class TestTest(TempdirManager,
phony_project = 'ohno_ohno-impossible_1234-name_stop-that!'
cmd.tests_require = [phony_project]
cmd.ensure_finalized()
logs = self.get_logs(logging.WARNING)
logs = self.get_logs()
self.assertIn(phony_project, logs[-1])
def prepare_a_module(self):
......
......@@ -129,7 +129,7 @@ class UploadTestCase(support.TempdirManager, support.EnvironRestorer,
dist_files = [(command, pyversion, filename)]
docs_path = os.path.join(self.tmp_dir, "build", "docs")
os.makedirs(docs_path)
self.write_file(os.path.join(docs_path, "index.html"), "yellow")
self.write_file((docs_path, "index.html"), "yellow")
self.write_file(self.rc, PYPIRC)
# let's run it
......
"""Tests for packaging.command.upload_docs."""
import os
import shutil
import logging
import zipfile
try:
import _ssl
......@@ -70,9 +71,8 @@ class UploadDocsTestCase(support.TempdirManager,
if sample_dir is None:
sample_dir = self.mkdtemp()
os.mkdir(os.path.join(sample_dir, "docs"))
self.write_file(os.path.join(sample_dir, "docs", "index.html"),
"Ce mortel ennui")
self.write_file(os.path.join(sample_dir, "index.html"), "Oh la la")
self.write_file((sample_dir, "docs", "index.html"), "Ce mortel ennui")
self.write_file((sample_dir, "index.html"), "Oh la la")
return sample_dir
def test_zip_dir(self):
......@@ -141,13 +141,16 @@ class UploadDocsTestCase(support.TempdirManager,
self.pypi.default_response_status = '403 Forbidden'
self.prepare_command()
self.cmd.run()
self.assertIn('Upload failed (403): Forbidden', self.get_logs()[-1])
errors = self.get_logs(logging.ERROR)
self.assertEqual(len(errors), 1)
self.assertIn('Upload failed (403): Forbidden', errors[0])
self.pypi.default_response_status = '301 Moved Permanently'
self.pypi.default_response_headers.append(
("Location", "brand_new_location"))
self.cmd.run()
self.assertIn('brand_new_location', self.get_logs()[-1])
lastlog = self.get_logs(logging.INFO)[-1]
self.assertIn('brand_new_location', lastlog)
def test_reads_pypirc_data(self):
self.write_file(self.rc, PYPIRC % self.pypi.full_address)
......@@ -171,7 +174,7 @@ class UploadDocsTestCase(support.TempdirManager,
self.prepare_command()
self.cmd.show_response = True
self.cmd.run()
record = self.get_logs()[-1]
record = self.get_logs(logging.INFO)[-1]
self.assertTrue(record, "should report the response")
self.assertIn(self.pypi.default_response_data, record)
......
"""Tests for packaging.config."""
import os
import sys
import logging
from io import StringIO
from packaging import command
......@@ -375,15 +374,14 @@ class ConfigTestCase(support.TempdirManager,
self.write_file('README', 'yeah')
self.write_file('hooks.py', HOOKS_MODULE)
self.get_dist()
logs = self.get_logs(logging.WARNING)
self.assertEqual(['logging_hook called'], logs)
self.assertEqual(['logging_hook called'], self.get_logs())
self.assertIn('hooks', sys.modules)
def test_missing_setup_hook_warns(self):
self.write_setup({'setup-hooks': 'this.does._not.exist'})
self.write_file('README', 'yeah')
self.get_dist()
logs = self.get_logs(logging.WARNING)
logs = self.get_logs()
self.assertEqual(1, len(logs))
self.assertIn('cannot find setup hook', logs[0])
......@@ -397,7 +395,7 @@ class ConfigTestCase(support.TempdirManager,
dist = self.get_dist()
self.assertEqual(['haven', 'first', 'third'], dist.py_modules)
logs = self.get_logs(logging.WARNING)
logs = self.get_logs()
self.assertEqual(1, len(logs))
self.assertIn('cannot find setup hook', logs[0])
......
......@@ -80,8 +80,7 @@ class CreateTestCase(support.TempdirManager,
os.mkdir(os.path.join(tempdir, dir_))
for file_ in files:
path = os.path.join(tempdir, file_)
self.write_file(path, 'xxx')
self.write_file((tempdir, file_), 'xxx')
mainprogram._find_files()
mainprogram.data['packages'].sort()
......
"""Tests for packaging.dist."""
import os
import sys
import logging
import textwrap
import packaging.dist
from packaging.dist import Distribution
from packaging.command import set_command
from packaging.command import set_command, _COMMANDS
from packaging.command.cmd import Command
from packaging.errors import PackagingModuleError, PackagingOptionError
from packaging.tests import captured_stdout
......@@ -29,6 +28,9 @@ class test_dist(Command):
def finalize_options(self):
pass
def run(self):
pass
class DistributionTestCase(support.TempdirManager,
support.LoggingCatcher,
......@@ -39,12 +41,18 @@ class DistributionTestCase(support.TempdirManager,
def setUp(self):
super(DistributionTestCase, self).setUp()
# XXX this is ugly, we should fix the functions to accept args
# (defaulting to sys.argv)
self.argv = sys.argv, sys.argv[:]
del sys.argv[1:]
self._commands = _COMMANDS.copy()
def tearDown(self):
sys.argv = self.argv[0]
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()
@unittest.skip('needs to be updated')
......@@ -74,7 +82,7 @@ class DistributionTestCase(support.TempdirManager,
'version': '1.2',
'home_page': 'xxxx',
'badoptname': 'xxx'})
logs = self.get_logs(logging.WARNING)
logs = self.get_logs()
self.assertEqual(len(logs), 1)
self.assertIn('unknown argument', logs[0])
......@@ -85,7 +93,7 @@ class DistributionTestCase(support.TempdirManager,
'version': '1.2', 'home_page': 'xxxx',
'options': {}})
self.assertEqual([], self.get_logs(logging.WARNING))
self.assertEqual(self.get_logs(), [])
self.assertNotIn('options', dir(dist))
def test_non_empty_options(self):
......
"""Tests for packaging.manifest."""
import os
import re
import logging
from io import StringIO
from packaging.errors import PackagingTemplateError
from packaging.manifest import Manifest, _translate_pattern, _glob_to_re
......@@ -37,10 +36,10 @@ class ManifestTestCase(support.TempdirManager,
super(ManifestTestCase, self).tearDown()
def assertNoWarnings(self):
self.assertEqual(self.get_logs(logging.WARNING), [])
self.assertEqual(self.get_logs(), [])
def assertWarnings(self):
self.assertGreater(len(self.get_logs(logging.WARNING)), 0)
self.assertNotEqual(self.get_logs(), [])
def test_manifest_reader(self):
tmpdir = self.mkdtemp()
......@@ -51,7 +50,7 @@ class ManifestTestCase(support.TempdirManager,
manifest = Manifest()
manifest.read_template(MANIFEST)
warnings = self.get_logs(logging.WARNING)
warnings = self.get_logs()
# the manifest should have been read and 3 warnings issued
# (we didn't provide the files)
self.assertEqual(3, len(warnings))
......
"""Tests for packaging.metadata."""
import os
import sys
import logging
from textwrap import dedent
from io import StringIO
......@@ -302,7 +301,7 @@ class MetadataTestCase(LoggingCatcher,
'name': 'xxx',
'version': 'xxx',
'home_page': 'xxxx'})
logs = self.get_logs(logging.WARNING)
logs = self.get_logs()
self.assertEqual(1, len(logs))
self.assertIn('not a valid version', logs[0])
......@@ -418,7 +417,7 @@ class MetadataTestCase(LoggingCatcher,
# XXX check PEP and see if 3 == 3.0
metadata['Requires-Python'] = '>=2.6, <3.0'
metadata['Requires-Dist'] = ['Foo (>=2.6, <3.0)']
self.assertEqual([], self.get_logs(logging.WARNING))
self.assertEqual(self.get_logs(), [])
@unittest.skip('needs to be implemented')
def test_requires_illegal(self):
......
import sys
import textwrap
from packaging.tests import unittest, support
......
......@@ -61,8 +61,7 @@ class UninstallTestCase(support.TempdirManager,
kw['pkg'] = pkg
pkg_dir = os.path.join(project_dir, pkg)
os.mkdir(pkg_dir)
os.mkdir(os.path.join(pkg_dir, 'sub'))
os.makedirs(os.path.join(pkg_dir, 'sub'))
self.write_file((project_dir, 'setup.cfg'), SETUP_CFG % kw)
self.write_file((pkg_dir, '__init__.py'), '#')
......
......@@ -4,6 +4,7 @@ import sys
import time
import logging
import tempfile
import textwrap
import subprocess
from io import StringIO
......@@ -355,55 +356,64 @@ class UtilTestCase(support.EnvironRestorer,
#
root = self.mkdtemp()
pkg1 = os.path.join(root, 'pkg1')
os.mkdir(pkg1)
self.write_file(os.path.join(pkg1, '__init__.py'))
os.mkdir(os.path.join(pkg1, 'pkg2'))
self.write_file(os.path.join(pkg1, 'pkg2', '__init__.py'))
os.mkdir(os.path.join(pkg1, 'pkg3'))
self.write_file(os.path.join(pkg1, 'pkg3', '__init__.py'))
os.mkdir(os.path.join(pkg1, 'pkg3', 'pkg6'))
self.write_file(os.path.join(pkg1, 'pkg3', 'pkg6', '__init__.py'))
os.mkdir(os.path.join(pkg1, 'pkg4'))
os.mkdir(os.path.join(pkg1, 'pkg4', 'pkg8'))
self.write_file(os.path.join(pkg1, 'pkg4', 'pkg8', '__init__.py'))
pkg5 = os.path.join(root, 'pkg5')
os.mkdir(pkg5)
self.write_file(os.path.join(pkg5, '__init__.py'))
os.makedirs(os.path.join(pkg1, 'pkg2'))
os.makedirs(os.path.join(pkg1, 'pkg3', 'pkg6'))
os.makedirs(os.path.join(pkg1, 'pkg4', 'pkg8'))
os.makedirs(os.path.join(root, 'pkg5'))
self.write_file((pkg1, '__init__.py'))
self.write_file((pkg1, 'pkg2', '__init__.py'))
self.write_file((pkg1, 'pkg3', '__init__.py'))
self.write_file((pkg1, 'pkg3', 'pkg6', '__init__.py'))
self.write_file((pkg1, 'pkg4', 'pkg8', '__init__.py'))
self.write_file((root, 'pkg5', '__init__.py'))
res = find_packages([root], ['pkg1.pkg2'])
self.assertEqual(set(res), set(['pkg1', 'pkg5', 'pkg1.pkg3',
'pkg1.pkg3.pkg6']))
self.assertEqual(sorted(res),
['pkg1', 'pkg1.pkg3', 'pkg1.pkg3.pkg6', 'pkg5'])
def test_resolve_name(self):
self.assertIs(str, resolve_name('builtins.str'))
self.assertEqual(
UtilTestCase.__name__,
resolve_name("packaging.tests.test_util.UtilTestCase").__name__)
self.assertEqual(
UtilTestCase.test_resolve_name.__name__,
resolve_name("packaging.tests.test_util.UtilTestCase."
"test_resolve_name").__name__)
self.assertRaises(ImportError, resolve_name,
"packaging.tests.test_util.UtilTestCaseNot")
self.assertRaises(ImportError, resolve_name,
"packaging.tests.test_util.UtilTestCase."
"nonexistent_attribute")
def test_import_nested_first_time(self):
tmp_dir = self.mkdtemp()
os.makedirs(os.path.join(tmp_dir, 'a', 'b'))
self.write_file(os.path.join(tmp_dir, 'a', '__init__.py'), '')
self.write_file(os.path.join(tmp_dir, 'a', 'b', '__init__.py'), '')
self.write_file(os.path.join(tmp_dir, 'a', 'b', 'c.py'),
'class Foo: pass')
try:
sys.path.append(tmp_dir)
resolve_name("a.b.c.Foo")
# assert nothing raised
finally:
sys.path.remove(tmp_dir)
# test raw module name
tmpdir = self.mkdtemp()
sys.path.append(tmpdir)
self.addCleanup(sys.path.remove, tmpdir)
self.write_file((tmpdir, 'hello.py'), '')
os.makedirs(os.path.join(tmpdir, 'a', 'b'))
self.write_file((tmpdir, 'a', '__init__.py'), '')
self.write_file((tmpdir, 'a', 'b', '__init__.py'), '')
self.write_file((tmpdir, 'a', 'b', 'c.py'), 'class Foo: pass')
self.write_file((tmpdir, 'a', 'b', 'd.py'), textwrap.dedent("""\
class FooBar:
class Bar:
def baz(self):
pass
"""))
# check Python, C and built-in module
self.assertEqual(resolve_name('hello').__name__, 'hello')
self.assertEqual(resolve_name('_csv').__name__, '_csv')
self.assertEqual(resolve_name('sys').__name__, 'sys')
# test module.attr
self.assertIs(resolve_name('builtins.str'), str)
self.assertIsNone(resolve_name('hello.__doc__'))
self.assertEqual(resolve_name('a.b.c.Foo').__name__, 'Foo')
self.assertEqual(resolve_name('a.b.d.FooBar.Bar.baz').__name__, 'baz')
# error if module not found
self.assertRaises(ImportError, resolve_name, 'nonexistent')
self.assertRaises(ImportError, resolve_name, 'non.existent')
self.assertRaises(ImportError, resolve_name, 'a.no')
self.assertRaises(ImportError, resolve_name, 'a.b.no')
self.assertRaises(ImportError, resolve_name, 'a.b.no.no')
self.assertRaises(ImportError, resolve_name, 'inva-lid')
# looking up built-in names is not supported
self.assertRaises(ImportError, resolve_name, 'str')
# error if module found but not attr
self.assertRaises(ImportError, resolve_name, 'a.b.Spam')
self.assertRaises(ImportError, resolve_name, 'a.b.c.Spam')
def test_run_2to3_on_code(self):
content = "print 'test'"
......
"""Tests for packaging.version."""
import doctest
import os
from packaging.version import NormalizedVersion as V
from packaging.version import HugeMajorVersionNumError, IrrationalVersionError
......@@ -46,7 +45,6 @@ class VersionTestCase(unittest.TestCase):
def test_from_parts(self):
for v, s in self.versions:
parts = v.parts
v2 = V.from_parts(*v.parts)
self.assertEqual(v, v2)
self.assertEqual(str(v), str(v2))
......@@ -192,7 +190,7 @@ class VersionTestCase(unittest.TestCase):
'Hey (>=2.5,<2.7)')
for predicate in predicates:
v = VersionPredicate(predicate)
VersionPredicate(predicate)
self.assertTrue(VersionPredicate('Hey (>=2.5,<2.7)').match('2.6'))
self.assertTrue(VersionPredicate('Ho').match('2.6'))
......
......@@ -630,22 +630,35 @@ def find_packages(paths=(os.curdir,), exclude=()):
def resolve_name(name):
"""Resolve a name like ``module.object`` to an object and return it.
Raise ImportError if the module or name is not found.
This functions supports packages and attributes without depth limitation:
``package.package.module.class.class.function.attr`` is valid input.
However, looking up builtins is not directly supported: use
``builtins.name``.
Raises ImportError if importing the module fails or if one requested
attribute is not found.
"""
if '.' not in name:
# shortcut
__import__(name)
return sys.modules[name]
# FIXME clean up this code!
parts = name.split('.')
cursor = len(parts)
module_name = parts[:cursor]
ret = ''
while cursor > 0:
try:
ret = __import__('.'.join(module_name))
break
except ImportError:
if cursor == 0:
raise
cursor -= 1
module_name = parts[:cursor]
ret = ''
if ret == '':
raise ImportError(parts[0])
for part in parts[1:]:
try:
......
......@@ -1455,7 +1455,7 @@ Tests
the amount of time needed to run the tests. "make test" and "make quicktest"
now include some resource-intensive tests, but no longer run the test suite
twice to check for bugs in .pyc generation. Tools/scripts/run_test.py provides
as an easy platform-independent way to run test suite with sensible defaults.
an easy platform-independent way to run test suite with sensible defaults.
- Issue #12331: The test suite for the packaging module can now run from an
installed Python.
......
......@@ -1380,8 +1380,7 @@ class PyBuildExt(build_ext):
# End multiprocessing
# Platform-specific libraries
if any(platform.startswith(prefix)
for prefix in ("linux", "freebsd", "gnukfreebsd")):
if platform.startswith(('linux', 'freebsd', 'gnukfreebsd')):
exts.append( Extension('ossaudiodev', ['ossaudiodev.c']) )
else:
missing.append('ossaudiodev')
......
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