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.
This commit is contained in:
parent
92ffc500d1
commit
6bbd775377
|
@ -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."""
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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')
|
||||
|
||||
# make sure update method checks values like the set method does
|
||||
metadata.update({'version': '1--2'})
|
||||
self.assertEqual(len(self.get_logs()), 1)
|
||||
|
||||
# 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_versions(self):
|
||||
metadata = Metadata()
|
||||
metadata['Obsoletes'] = 'ok'
|
||||
self.assertEqual(metadata['Metadata-Version'], '1.1')
|
||||
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']}
|
||||
|
||||
del metadata['Obsoletes']
|
||||
metadata['Obsoletes-Dist'] = 'ok'
|
||||
self.assertEqual(metadata['Metadata-Version'], '1.2')
|
||||
metadata = Metadata(mapping=fields)
|
||||
PKG_INFO = StringIO()
|
||||
metadata.write_file(PKG_INFO)
|
||||
PKG_INFO.seek(0)
|
||||
|
||||
self.assertRaises(MetadataConflictError, metadata.set,
|
||||
'Obsoletes', 'ok')
|
||||
metadata = Metadata(fileobj=PKG_INFO)
|
||||
|
||||
del metadata['Obsoletes']
|
||||
del metadata['Obsoletes-Dist']
|
||||
metadata['Version'] = '1'
|
||||
self.assertEqual(metadata['Metadata-Version'], '1.0')
|
||||
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'])
|
||||
|
||||
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')
|
||||
def test_write_metadata(self):
|
||||
# check support of non-ASCII values
|
||||
tmp_dir = self.mkdtemp()
|
||||
my_file = os.path.join(tmp_dir, 'f')
|
||||
|
||||
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')
|
||||
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)
|
||||
|
||||
# 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)
|
||||
# the file should use UTF-8
|
||||
metadata2 = Metadata()
|
||||
with open(my_file, encoding='utf-8') as fp:
|
||||
metadata2.read_file(fp)
|
||||
|
||||
def test_warnings(self):
|
||||
metadata = Metadata()
|
||||
# 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())
|
||||
|
||||
# these should raise a warning
|
||||
values = (('Requires-Dist', 'Funky (Groovie)'),
|
||||
('Requires-Python', '1-4'))
|
||||
# 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)
|
||||
|
||||
for name, value in values:
|
||||
metadata.set(name, value)
|
||||
metadata2 = Metadata()
|
||||
with open(my_file, encoding='utf-8') as fp:
|
||||
metadata2.read_file(fp)
|
||||
|
||||
# we should have a certain amount of warnings
|
||||
self.assertEqual(len(self.get_logs()), 2)
|
||||
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)
|
||||
|
||||
def test_multiple_predicates(self):
|
||||
metadata = Metadata()
|
||||
out.seek(0)
|
||||
res = Metadata()
|
||||
res.read_file(out)
|
||||
self.assertEqual(metadata.values(), res.values())
|
||||
|
||||
# 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)']
|
||||
|
||||
self.assertEqual([], self.get_logs(logging.WARNING))
|
||||
|
||||
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')
|
||||
|
||||
file_.seek(0)
|
||||
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(file_)
|
||||
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)
|
||||
|
||||
out.seek(0)
|
||||
metadata = Metadata()
|
||||
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)
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue