diff options
author | Éric Araujo <merwok@netwok.org> | 2011-09-10 03:18:20 (GMT) |
---|---|---|
committer | Éric Araujo <merwok@netwok.org> | 2011-09-10 03:18:20 (GMT) |
commit | 6bbd775377ae4a6e87ccce990750ac02afe83573 (patch) | |
tree | e794c3ba5ecf0144ff6cd523777f4d774759fbbe | |
parent | 92ffc500d1b218d533953c8b7a79733902125f9c (diff) | |
download | cpython-6bbd775377ae4a6e87ccce990750ac02afe83573.zip cpython-6bbd775377ae4a6e87ccce990750ac02afe83573.tar.gz cpython-6bbd775377ae4a6e87ccce990750ac02afe83573.tar.bz2 |
Consolidate tests for packaging.metadata.
New tests were added in test_metadata and old tests inherited from
distutils were still in test_dist, so I moved them into test_metadata
(except for one which was more at home in test_run) and merged
duplicates.
I also added some skips to lure contributors <wink>, optimized the
Metadata.update method a trifle, and added notes about a number of
issues.
A note: The tests in test_dist used to dump the Metadata objects to a
file in the METADATA format and look for strings in its contents; I
updated them to use the mapping API of Metadata instead. For some
fields with special writing rules, I have added tests to ensure my
conversion did not lose anything.
-rw-r--r-- | Lib/packaging/metadata.py | 14 | ||||
-rw-r--r-- | Lib/packaging/tests/test_dist.py | 252 | ||||
-rw-r--r-- | Lib/packaging/tests/test_metadata.py | 395 | ||||
-rw-r--r-- | Lib/packaging/tests/test_run.py | 23 |
4 files changed, 333 insertions, 351 deletions
diff --git a/Lib/packaging/metadata.py b/Lib/packaging/metadata.py index 104600b..7d7fc6b 100644 --- a/Lib/packaging/metadata.py +++ b/Lib/packaging/metadata.py @@ -354,11 +354,20 @@ class Metadata: Keys that don't match a metadata field or that have an empty value are dropped. """ + # XXX the code should just use self.set, which does tbe same checks and + # conversions already, but that would break packaging.pypi: it uses the + # update method, which does not call _set_best_version (which set + # does), and thus allows having a Metadata object (as long as you don't + # modify or write it) with extra fields from PyPI that are not fields + # defined in Metadata PEPs. to solve it, the best_version system + # should be reworked so that it's called only for writing, or in a new + # strict mode, or with a new, more lax Metadata subclass in p7g.pypi def _set(key, value): if key in _ATTR2FIELD and value: self.set(self._convert_name(key), value) - if other is None: + if not other: + # other is None or empty container pass elif hasattr(other, 'keys'): for k in other.keys(): @@ -368,7 +377,8 @@ class Metadata: _set(k, v) if kwargs: - self.update(kwargs) + for k, v in kwargs.items(): + _set(k, v) def set(self, name, value): """Control then set a metadata field.""" diff --git a/Lib/packaging/tests/test_dist.py b/Lib/packaging/tests/test_dist.py index 1d78fa9..bd86245 100644 --- a/Lib/packaging/tests/test_dist.py +++ b/Lib/packaging/tests/test_dist.py @@ -1,16 +1,13 @@ """Tests for packaging.dist.""" import os -import io import sys import logging import textwrap -import sysconfig import packaging.dist from packaging.dist import Distribution from packaging.command import set_command from packaging.command.cmd import Command -from packaging.metadata import Metadata from packaging.errors import PackagingModuleError, PackagingOptionError from packaging.tests import TESTFN, captured_stdout from packaging.tests import support, unittest @@ -49,6 +46,7 @@ class DistributionTestCase(support.TempdirManager, sys.argv[:] = self.argv[1] super(DistributionTestCase, self).tearDown() + @unittest.skip('needs to be updated') def test_debug_mode(self): self.addCleanup(os.unlink, TESTFN) with open(TESTFN, "w") as f: @@ -59,6 +57,8 @@ class DistributionTestCase(support.TempdirManager, sys.argv.append("build") __, stdout = captured_stdout(create_distribution, files) self.assertEqual(stdout, '') + # XXX debug mode does not exist anymore, test logging levels in this + # test instead packaging.dist.DEBUG = True try: __, stdout = captured_stdout(create_distribution, files) @@ -66,34 +66,6 @@ class DistributionTestCase(support.TempdirManager, finally: packaging.dist.DEBUG = False - def test_write_pkg_file(self): - # Check Metadata handling of Unicode fields - tmp_dir = self.mkdtemp() - my_file = os.path.join(tmp_dir, 'f') - cls = Distribution - - dist = cls(attrs={'author': 'Mister Café', - 'name': 'my.package', - 'maintainer': 'Café Junior', - 'summary': 'Café torréfié', - 'description': 'Héhéhé'}) - - # let's make sure the file can be written - # with Unicode fields. they are encoded with - # PKG_INFO_ENCODING - with open(my_file, 'w', encoding='utf-8') as fp: - dist.metadata.write_file(fp) - - # regular ascii is of course always usable - dist = cls(attrs={'author': 'Mister Cafe', - 'name': 'my.package', - 'maintainer': 'Cafe Junior', - 'summary': 'Cafe torrefie', - 'description': 'Hehehe'}) - - with open(my_file, 'w') as fp: - dist.metadata.write_file(fp) - def test_bad_attr(self): Distribution(attrs={'author': 'xxx', 'name': 'xxx', @@ -101,28 +73,18 @@ class DistributionTestCase(support.TempdirManager, 'home-page': 'xxxx', 'badoptname': 'xxx'}) logs = self.get_logs(logging.WARNING) - self.assertEqual(1, len(logs)) + self.assertEqual(len(logs), 1) self.assertIn('unknown argument', logs[0]) - def test_bad_version(self): - Distribution(attrs={'author': 'xxx', - 'name': 'xxx', - 'version': 'xxx', - 'home-page': 'xxxx'}) - logs = self.get_logs(logging.WARNING) - self.assertEqual(1, len(logs)) - self.assertIn('not a valid version', logs[0]) - def test_empty_options(self): # an empty options dictionary should not stay in the # list of attributes - Distribution(attrs={'author': 'xxx', - 'name': 'xxx', - 'version': '1.2', - 'home-page': 'xxxx', - 'options': {}}) + dist = Distribution(attrs={'author': 'xxx', 'name': 'xxx', + 'version': '1.2', 'home-page': 'xxxx', + 'options': {}}) self.assertEqual([], self.get_logs(logging.WARNING)) + self.assertNotIn('options', dir(dist)) def test_non_empty_options(self): # TODO: how to actually use options is not documented except @@ -141,7 +103,6 @@ class DistributionTestCase(support.TempdirManager, self.assertIn('owner', dist.get_option_dict('sdist')) def test_finalize_options(self): - attrs = {'keywords': 'one,two', 'platform': 'one,two'} @@ -152,6 +113,24 @@ class DistributionTestCase(support.TempdirManager, self.assertEqual(dist.metadata['platform'], ['one', 'two']) self.assertEqual(dist.metadata['keywords'], ['one', 'two']) + def test_custom_pydistutils(self): + # Bug #2166: make sure pydistutils.cfg is found + if os.name == 'posix': + user_filename = ".pydistutils.cfg" + else: + user_filename = "pydistutils.cfg" + + temp_dir = self.mkdtemp() + user_filename = os.path.join(temp_dir, user_filename) + with open(user_filename, 'w') as f: + f.write('.') + + dist = Distribution() + + os.environ['HOME'] = temp_dir + files = dist.find_config_files() + self.assertIn(user_filename, files) + def test_find_config_files_disable(self): # Bug #1180: Allow users to disable their own config file. temp_home = self.mkdtemp() @@ -270,185 +249,8 @@ class DistributionTestCase(support.TempdirManager, self.assertRaises(PackagingOptionError, d.run_command, 'test_dist') -class MetadataTestCase(support.TempdirManager, - support.LoggingCatcher, - support.EnvironRestorer, - unittest.TestCase): - - restore_environ = ['HOME'] - - def setUp(self): - super(MetadataTestCase, self).setUp() - self.argv = sys.argv, sys.argv[:] - - def tearDown(self): - sys.argv = self.argv[0] - sys.argv[:] = self.argv[1] - super(MetadataTestCase, self).tearDown() - - def test_simple_metadata(self): - attrs = {"name": "package", - "version": "1.0"} - dist = Distribution(attrs) - meta = self.format_metadata(dist) - self.assertIn("Metadata-Version: 1.0", meta) - self.assertNotIn("provides:", meta.lower()) - self.assertNotIn("requires:", meta.lower()) - self.assertNotIn("obsoletes:", meta.lower()) - - def test_provides_dist(self): - attrs = {"name": "package", - "version": "1.0", - "provides_dist": ["package", "package.sub"]} - dist = Distribution(attrs) - self.assertEqual(dist.metadata['Provides-Dist'], - ["package", "package.sub"]) - meta = self.format_metadata(dist) - self.assertIn("Metadata-Version: 1.2", meta) - self.assertNotIn("requires:", meta.lower()) - self.assertNotIn("obsoletes:", meta.lower()) - - def _test_provides_illegal(self): - # XXX to do: check the versions - self.assertRaises(ValueError, Distribution, - {"name": "package", - "version": "1.0", - "provides_dist": ["my.pkg (splat)"]}) - - def test_requires_dist(self): - attrs = {"name": "package", - "version": "1.0", - "requires_dist": ["other", "another (==1.0)"]} - dist = Distribution(attrs) - self.assertEqual(dist.metadata['Requires-Dist'], - ["other", "another (==1.0)"]) - meta = self.format_metadata(dist) - self.assertIn("Metadata-Version: 1.2", meta) - self.assertNotIn("provides:", meta.lower()) - self.assertIn("Requires-Dist: other", meta) - self.assertIn("Requires-Dist: another (==1.0)", meta) - self.assertNotIn("obsoletes:", meta.lower()) - - def _test_requires_illegal(self): - # XXX - self.assertRaises(ValueError, Distribution, - {"name": "package", - "version": "1.0", - "requires": ["my.pkg (splat)"]}) - - def test_obsoletes_dist(self): - attrs = {"name": "package", - "version": "1.0", - "obsoletes_dist": ["other", "another (<1.0)"]} - dist = Distribution(attrs) - self.assertEqual(dist.metadata['Obsoletes-Dist'], - ["other", "another (<1.0)"]) - meta = self.format_metadata(dist) - self.assertIn("Metadata-Version: 1.2", meta) - self.assertNotIn("provides:", meta.lower()) - self.assertNotIn("requires:", meta.lower()) - self.assertIn("Obsoletes-Dist: other", meta) - self.assertIn("Obsoletes-Dist: another (<1.0)", meta) - - def _test_obsoletes_illegal(self): - # XXX - self.assertRaises(ValueError, Distribution, - {"name": "package", - "version": "1.0", - "obsoletes": ["my.pkg (splat)"]}) - - def format_metadata(self, dist): - sio = io.StringIO() - dist.metadata.write_file(sio) - return sio.getvalue() - - def test_custom_pydistutils(self): - # fixes #2166 - # make sure pydistutils.cfg is found - if os.name == 'posix': - user_filename = ".pydistutils.cfg" - else: - user_filename = "pydistutils.cfg" - - temp_dir = self.mkdtemp() - user_filename = os.path.join(temp_dir, user_filename) - with open(user_filename, 'w') as f: - f.write('.') - - dist = Distribution() - - # linux-style - if sys.platform in ('linux', 'darwin'): - os.environ['HOME'] = temp_dir - files = dist.find_config_files() - self.assertIn(user_filename, files) - - # win32-style - if sys.platform == 'win32': - # home drive should be found - os.environ['HOME'] = temp_dir - files = dist.find_config_files() - self.assertIn(user_filename, files) - - def test_show_help(self): - # smoke test, just makes sure some help is displayed - dist = Distribution() - sys.argv = [] - dist.help = True - dist.script_name = os.path.join(sysconfig.get_path('scripts'), - 'pysetup') - __, stdout = captured_stdout(dist.parse_command_line) - output = [line for line in stdout.split('\n') - if line.strip() != ''] - self.assertGreater(len(output), 0) - - def test_description(self): - desc = textwrap.dedent("""\ - example:: - We start here - and continue here - and end here.""") - attrs = {"name": "package", - "version": "1.0", - "description": desc} - - dist = packaging.dist.Distribution(attrs) - meta = self.format_metadata(dist) - meta = meta.replace('\n' + 7 * ' ' + '|', '\n') - self.assertIn(desc, meta) - - def test_read_metadata(self): - attrs = {"name": "package", - "version": "1.0", - "description": "desc", - "summary": "xxx", - "download_url": "http://example.com", - "keywords": ['one', 'two'], - "requires_dist": ['foo']} - - dist = Distribution(attrs) - PKG_INFO = io.StringIO() - dist.metadata.write_file(PKG_INFO) - PKG_INFO.seek(0) - - metadata = Metadata() - metadata.read_file(PKG_INFO) - - self.assertEqual(metadata['name'], "package") - self.assertEqual(metadata['version'], "1.0") - self.assertEqual(metadata['summary'], "xxx") - self.assertEqual(metadata['download_url'], 'http://example.com') - self.assertEqual(metadata['keywords'], ['one', 'two']) - self.assertEqual(metadata['platform'], []) - self.assertEqual(metadata['obsoletes'], []) - self.assertEqual(metadata['requires-dist'], ['foo']) - - def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(DistributionTestCase)) - suite.addTest(unittest.makeSuite(MetadataTestCase)) - return suite + return unittest.makeSuite(DistributionTestCase) if __name__ == "__main__": unittest.main(defaultTest="test_suite") diff --git a/Lib/packaging/tests/test_metadata.py b/Lib/packaging/tests/test_metadata.py index 904019c..b79f566 100644 --- a/Lib/packaging/tests/test_metadata.py +++ b/Lib/packaging/tests/test_metadata.py @@ -2,6 +2,7 @@ import os import sys import logging +from textwrap import dedent from io import StringIO from packaging.errors import (MetadataConflictError, MetadataMissingError, @@ -9,12 +10,29 @@ from packaging.errors import (MetadataConflictError, MetadataMissingError, from packaging.metadata import Metadata, PKG_INFO_PREFERRED_VERSION from packaging.tests import unittest -from packaging.tests.support import LoggingCatcher +from packaging.tests.support import (LoggingCatcher, TempdirManager, + EnvironRestorer) class MetadataTestCase(LoggingCatcher, + TempdirManager, + EnvironRestorer, unittest.TestCase): + maxDiff = None + restore_environ = ['HOME'] + + def setUp(self): + super(MetadataTestCase, self).setUp() + self.argv = sys.argv, sys.argv[:] + + def tearDown(self): + sys.argv = self.argv[0] + sys.argv[:] = self.argv[1] + super(MetadataTestCase, self).tearDown() + + #### Test various methods of the Metadata class + def test_instantiation(self): PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO') with open(PKG_INFO, 'r', encoding='utf-8') as f: @@ -43,17 +61,6 @@ class MetadataTestCase(LoggingCatcher, self.assertRaises(TypeError, Metadata, PKG_INFO, mapping=m, fileobj=fp) - def test_metadata_read_write(self): - PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO') - metadata = Metadata(PKG_INFO) - out = StringIO() - metadata.write_file(out) - out.seek(0) - res = Metadata() - res.read_file(out) - for k in metadata: - self.assertEqual(metadata[k], res[k]) - def test_metadata_markers(self): # see if we can be platform-aware PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO') @@ -70,31 +77,10 @@ class MetadataTestCase(LoggingCatcher, # test with context context = {'sys.platform': 'okook'} - metadata = Metadata(platform_dependent=True, - execution_context=context) + metadata = Metadata(platform_dependent=True, execution_context=context) metadata.read_file(StringIO(content)) self.assertEqual(metadata['Requires-Dist'], ['foo']) - def test_description(self): - PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO') - with open(PKG_INFO, 'r', encoding='utf-8') as f: - content = f.read() % sys.platform - metadata = Metadata() - metadata.read_file(StringIO(content)) - - # see if we can read the description now - DESC = os.path.join(os.path.dirname(__file__), 'LONG_DESC.txt') - with open(DESC) as f: - wanted = f.read() - self.assertEqual(wanted, metadata['Description']) - - # save the file somewhere and make sure we can read it back - out = StringIO() - metadata.write_file(out) - out.seek(0) - metadata.read_file(out) - self.assertEqual(wanted, metadata['Description']) - def test_mapping_api(self): PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO') with open(PKG_INFO, 'r', encoding='utf-8') as f: @@ -109,73 +95,86 @@ class MetadataTestCase(LoggingCatcher, metadata.update([('version', '0.7')]) self.assertEqual(metadata['Version'], '0.7') - self.assertEqual(list(metadata), list(metadata.keys())) - - def test_versions(self): - metadata = Metadata() - metadata['Obsoletes'] = 'ok' - self.assertEqual(metadata['Metadata-Version'], '1.1') - - del metadata['Obsoletes'] - metadata['Obsoletes-Dist'] = 'ok' - self.assertEqual(metadata['Metadata-Version'], '1.2') - - self.assertRaises(MetadataConflictError, metadata.set, - 'Obsoletes', 'ok') - - del metadata['Obsoletes'] - del metadata['Obsoletes-Dist'] - metadata['Version'] = '1' - self.assertEqual(metadata['Metadata-Version'], '1.0') - - PKG_INFO = os.path.join(os.path.dirname(__file__), - 'SETUPTOOLS-PKG-INFO') - with open(PKG_INFO, 'r', encoding='utf-8') as f: - content = f.read() - metadata.read_file(StringIO(content)) - self.assertEqual(metadata['Metadata-Version'], '1.0') + # make sure update method checks values like the set method does + metadata.update({'version': '1--2'}) + self.assertEqual(len(self.get_logs()), 1) - PKG_INFO = os.path.join(os.path.dirname(__file__), - 'SETUPTOOLS-PKG-INFO2') - with open(PKG_INFO, 'r', encoding='utf-8') as f: - content = f.read() - metadata.read_file(StringIO(content)) - self.assertEqual(metadata['Metadata-Version'], '1.1') - - # Update the _fields dict directly to prevent 'Metadata-Version' - # from being updated by the _set_best_version() method. - metadata._fields['Metadata-Version'] = '1.618' - self.assertRaises(MetadataUnrecognizedVersionError, metadata.keys) - - def test_warnings(self): - metadata = Metadata() - - # these should raise a warning - values = (('Requires-Dist', 'Funky (Groovie)'), - ('Requires-Python', '1-4')) - - for name, value in values: - metadata.set(name, value) - - # we should have a certain amount of warnings - self.assertEqual(len(self.get_logs()), 2) + # XXX caveat: the keys method and friends are not 3.x-style views + # should be changed or documented + self.assertEqual(list(metadata), list(metadata.keys())) - def test_multiple_predicates(self): - metadata = Metadata() + def test_read_metadata(self): + fields = {'name': 'project', + 'version': '1.0', + 'description': 'desc', + 'summary': 'xxx', + 'download_url': 'http://example.com', + 'keywords': ['one', 'two'], + 'requires_dist': ['foo']} + + metadata = Metadata(mapping=fields) + PKG_INFO = StringIO() + metadata.write_file(PKG_INFO) + PKG_INFO.seek(0) + + metadata = Metadata(fileobj=PKG_INFO) + + self.assertEqual(metadata['name'], 'project') + self.assertEqual(metadata['version'], '1.0') + self.assertEqual(metadata['summary'], 'xxx') + self.assertEqual(metadata['download_url'], 'http://example.com') + self.assertEqual(metadata['keywords'], ['one', 'two']) + self.assertEqual(metadata['platform'], []) + self.assertEqual(metadata['obsoletes'], []) + self.assertEqual(metadata['requires-dist'], ['foo']) + + def test_write_metadata(self): + # check support of non-ASCII values + tmp_dir = self.mkdtemp() + my_file = os.path.join(tmp_dir, 'f') + + metadata = Metadata(mapping={'author': 'Mister Café', + 'name': 'my.project', + 'author': 'Café Junior', + 'summary': 'Café torréfié', + 'description': 'Héhéhé', + 'keywords': ['café', 'coffee']}) + metadata.write(my_file) + + # the file should use UTF-8 + metadata2 = Metadata() + with open(my_file, encoding='utf-8') as fp: + metadata2.read_file(fp) + + # XXX when keywords are not defined, metadata will have + # 'Keywords': [] but metadata2 will have 'Keywords': [''] + # because of a value.split(',') in Metadata.get + self.assertEqual(metadata.items(), metadata2.items()) + + # ASCII also works, it's a subset of UTF-8 + metadata = Metadata(mapping={'author': 'Mister Cafe', + 'name': 'my.project', + 'author': 'Cafe Junior', + 'summary': 'Cafe torrefie', + 'description': 'Hehehe'}) + metadata.write(my_file) + + metadata2 = Metadata() + with open(my_file, encoding='utf-8') as fp: + metadata2.read_file(fp) - # see for "3" instead of "3.0" ??? - # its seems like the MINOR VERSION can be omitted - metadata['Requires-Python'] = '>=2.6, <3.0' - metadata['Requires-Dist'] = ['Foo (>=2.6, <3.0)'] + def test_metadata_read_write(self): + PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO') + metadata = Metadata(PKG_INFO) + out = StringIO() + metadata.write_file(out) - self.assertEqual([], self.get_logs(logging.WARNING)) + out.seek(0) + res = Metadata() + res.read_file(out) + self.assertEqual(metadata.values(), res.values()) - def test_project_url(self): - metadata = Metadata() - metadata['Project-URL'] = [('one', 'http://ok')] - self.assertEqual(metadata['Project-URL'], - [('one', 'http://ok')]) - self.assertEqual(metadata['Metadata-Version'], '1.2') + #### Test checks def test_check_version(self): metadata = Metadata() @@ -238,39 +237,203 @@ class MetadataTestCase(LoggingCatcher, metadata['Requires-dist'] = ['Foo (a)'] metadata['Obsoletes-dist'] = ['Foo (a)'] metadata['Provides-dist'] = ['Foo (a)'] - if metadata.docutils_support: - missing, warnings = metadata.check() - self.assertEqual(len(warnings), 4) - metadata.docutils_support = False missing, warnings = metadata.check() self.assertEqual(len(warnings), 4) - def test_best_choice(self): - metadata = Metadata() - metadata['Version'] = '1.0' + #### Test fields and metadata versions + + def test_metadata_versions(self): + metadata = Metadata(mapping={'name': 'project', 'version': '1.0'}) self.assertEqual(metadata['Metadata-Version'], PKG_INFO_PREFERRED_VERSION) + self.assertNotIn('Provides', metadata) + self.assertNotIn('Requires', metadata) + self.assertNotIn('Obsoletes', metadata) + metadata['Classifier'] = ['ok'] self.assertEqual(metadata['Metadata-Version'], '1.2') - def test_project_urls(self): - # project-url is a bit specific, make sure we write it - # properly in PKG-INFO metadata = Metadata() - metadata['Version'] = '1.0' - metadata['Project-Url'] = [('one', 'http://ok')] - self.assertEqual(metadata['Project-Url'], [('one', 'http://ok')]) - file_ = StringIO() - metadata.write_file(file_) - file_.seek(0) - res = file_.read().split('\n') - self.assertIn('Project-URL: one,http://ok', res) + metadata['Obsoletes'] = 'ok' + self.assertEqual(metadata['Metadata-Version'], '1.1') + + del metadata['Obsoletes'] + metadata['Obsoletes-Dist'] = 'ok' + self.assertEqual(metadata['Metadata-Version'], '1.2') + + self.assertRaises(MetadataConflictError, metadata.set, + 'Obsoletes', 'ok') + + del metadata['Obsoletes'] + del metadata['Obsoletes-Dist'] + metadata['Version'] = '1' + self.assertEqual(metadata['Metadata-Version'], '1.0') + + PKG_INFO = os.path.join(os.path.dirname(__file__), + 'SETUPTOOLS-PKG-INFO') + metadata = Metadata(PKG_INFO) + self.assertEqual(metadata['Metadata-Version'], '1.0') + + PKG_INFO = os.path.join(os.path.dirname(__file__), + 'SETUPTOOLS-PKG-INFO2') + metadata = Metadata(PKG_INFO) + self.assertEqual(metadata['Metadata-Version'], '1.1') + + # Update the _fields dict directly to prevent 'Metadata-Version' + # from being updated by the _set_best_version() method. + metadata._fields['Metadata-Version'] = '1.618' + self.assertRaises(MetadataUnrecognizedVersionError, metadata.keys) + + def test_version(self): + Metadata(mapping={'author': 'xxx', + 'name': 'xxx', + 'version': 'xxx', + 'home-page': 'xxxx'}) + logs = self.get_logs(logging.WARNING) + self.assertEqual(1, len(logs)) + self.assertIn('not a valid version', logs[0]) + + def test_description(self): + PKG_INFO = os.path.join(os.path.dirname(__file__), 'PKG-INFO') + with open(PKG_INFO, 'r', encoding='utf-8') as f: + content = f.read() % sys.platform + metadata = Metadata() + metadata.read_file(StringIO(content)) + + # see if we can read the description now + DESC = os.path.join(os.path.dirname(__file__), 'LONG_DESC.txt') + with open(DESC) as f: + wanted = f.read() + self.assertEqual(wanted, metadata['Description']) + + # save the file somewhere and make sure we can read it back + out = StringIO() + metadata.write_file(out) + out.seek(0) - file_.seek(0) + out.seek(0) metadata = Metadata() - metadata.read_file(file_) + metadata.read_file(out) + self.assertEqual(wanted, metadata['Description']) + + def test_description_folding(self): + # make sure the indentation is preserved + out = StringIO() + desc = dedent("""\ + example:: + We start here + and continue here + and end here. + """) + + metadata = Metadata() + metadata['description'] = desc + metadata.write_file(out) + + folded_desc = desc.replace('\n', '\n' + (7 * ' ') + '|') + self.assertIn(folded_desc, out.getvalue()) + + def test_project_url(self): + metadata = Metadata() + metadata['Project-URL'] = [('one', 'http://ok')] + self.assertEqual(metadata['Project-URL'], [('one', 'http://ok')]) + self.assertEqual(metadata['Metadata-Version'], '1.2') + + # make sure this particular field is handled properly when written + fp = StringIO() + metadata.write_file(fp) + self.assertIn('Project-URL: one,http://ok', fp.getvalue().split('\n')) + + fp.seek(0) + metadata = Metadata() + metadata.read_file(fp) self.assertEqual(metadata['Project-Url'], [('one', 'http://ok')]) + # TODO copy tests for v1.1 requires, obsoletes and provides from distutils + # (they're useless but we support them so we should test them anyway) + + def test_provides_dist(self): + fields = {'name': 'project', + 'version': '1.0', + 'provides_dist': ['project', 'my.project']} + metadata = Metadata(mapping=fields) + self.assertEqual(metadata['Provides-Dist'], + ['project', 'my.project']) + self.assertEqual(metadata['Metadata-Version'], '1.2', metadata) + self.assertNotIn('Requires', metadata) + self.assertNotIn('Obsoletes', metadata) + + @unittest.skip('needs to be implemented') + def test_provides_illegal(self): + # TODO check the versions (like distutils does for old provides field) + self.assertRaises(ValueError, Metadata, + mapping={'name': 'project', + 'version': '1.0', + 'provides_dist': ['my.pkg (splat)']}) + + def test_requires_dist(self): + fields = {'name': 'project', + 'version': '1.0', + 'requires_dist': ['other', 'another (==1.0)']} + metadata = Metadata(mapping=fields) + self.assertEqual(metadata['Requires-Dist'], + ['other', 'another (==1.0)']) + self.assertEqual(metadata['Metadata-Version'], '1.2') + self.assertNotIn('Provides', metadata) + self.assertEqual(metadata['Requires-Dist'], + ['other', 'another (==1.0)']) + self.assertNotIn('Obsoletes', metadata) + + # make sure write_file uses one RFC 822 header per item + fp = StringIO() + metadata.write_file(fp) + lines = fp.getvalue().split('\n') + self.assertIn('Requires-Dist: other', lines) + self.assertIn('Requires-Dist: another (==1.0)', lines) + + # test warnings for invalid version predicates + # XXX this would cause no warnings if we used update (or the mapping + # argument of the constructor), see comment in Metadata.update + metadata = Metadata() + metadata['Requires-Dist'] = 'Funky (Groovie)' + metadata['Requires-Python'] = '1-4' + self.assertEqual(len(self.get_logs()), 2) + + # test multiple version predicates + metadata = Metadata() + + # 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)) + + @unittest.skip('needs to be implemented') + def test_requires_illegal(self): + self.assertRaises(ValueError, Metadata, + mapping={'name': 'project', + 'version': '1.0', + 'requires': ['my.pkg (splat)']}) + + def test_obsoletes_dist(self): + fields = {'name': 'project', + 'version': '1.0', + 'obsoletes_dist': ['other', 'another (<1.0)']} + metadata = Metadata(mapping=fields) + self.assertEqual(metadata['Obsoletes-Dist'], + ['other', 'another (<1.0)']) + self.assertEqual(metadata['Metadata-Version'], '1.2') + self.assertNotIn('Provides', metadata) + self.assertNotIn('Requires', metadata) + self.assertEqual(metadata['Obsoletes-Dist'], + ['other', 'another (<1.0)']) + + @unittest.skip('needs to be implemented') + def test_obsoletes_illegal(self): + self.assertRaises(ValueError, Metadata, + mapping={'name': 'project', + 'version': '1.0', + 'obsoletes': ['my.pkg (splat)']}) + def test_suite(): return unittest.makeSuite(MetadataTestCase) diff --git a/Lib/packaging/tests/test_run.py b/Lib/packaging/tests/test_run.py index cb576b7..6a3b8fb 100644 --- a/Lib/packaging/tests/test_run.py +++ b/Lib/packaging/tests/test_run.py @@ -3,16 +3,16 @@ import os import sys import shutil -from tempfile import mkstemp from io import StringIO from packaging import install from packaging.tests import unittest, support, TESTFN from packaging.run import main +from test.script_helper import assert_python_ok + # setup script that uses __file__ setup_using___file__ = """\ - __file__ from packaging.run import setup @@ -20,7 +20,6 @@ setup() """ setup_prints_cwd = """\ - import os print os.getcwd() @@ -29,11 +28,12 @@ setup() """ -class CoreTestCase(support.TempdirManager, support.LoggingCatcher, - unittest.TestCase): +class RunTestCase(support.TempdirManager, + support.LoggingCatcher, + unittest.TestCase): def setUp(self): - super(CoreTestCase, self).setUp() + super(RunTestCase, self).setUp() self.old_stdout = sys.stdout self.cleanup_testfn() self.old_argv = sys.argv, sys.argv[:] @@ -43,7 +43,7 @@ class CoreTestCase(support.TempdirManager, support.LoggingCatcher, self.cleanup_testfn() sys.argv = self.old_argv[0] sys.argv[:] = self.old_argv[1] - super(CoreTestCase, self).tearDown() + super(RunTestCase, self).tearDown() def cleanup_testfn(self): path = TESTFN @@ -77,9 +77,16 @@ class CoreTestCase(support.TempdirManager, support.LoggingCatcher, os.chmod(install_path, old_mod) install.get_path = old_get_path + def test_show_help(self): + # smoke test, just makes sure some help is displayed + status, out, err = assert_python_ok('-m', 'packaging.run', '--help') + self.assertEqual(status, 0) + self.assertGreater(out, b'') + self.assertEqual(err, b'') + def test_suite(): - return unittest.makeSuite(CoreTestCase) + return unittest.makeSuite(RunTestCase) if __name__ == "__main__": unittest.main(defaultTest="test_suite") |