Commit 1690ef36 authored by Fred Drake's avatar Fred Drake

PEP 314 implementation (client side):

added support for the provides, requires, and obsoletes metadata fields
parent 5a3290c3
......@@ -231,7 +231,13 @@ Your selection [default 1]: ''',
'platform': meta.get_platforms(),
'classifiers': meta.get_classifiers(),
'download_url': meta.get_download_url(),
# PEP 314
'provides': meta.get_provides(),
'requires': meta.get_requires(),
'obsoletes': meta.get_obsoletes(),
}
if data['provides'] or data['requires'] or data['obsoletes']:
data['metadata_version'] = '1.1'
return data
def post_to_server(self, data, auth=None):
......
......@@ -47,7 +47,9 @@ setup_keywords = ('distclass', 'script_name', 'script_args', 'options',
'name', 'version', 'author', 'author_email',
'maintainer', 'maintainer_email', 'url', 'license',
'description', 'long_description', 'keywords',
'platforms', 'classifiers', 'download_url',)
'platforms', 'classifiers', 'download_url',
'requires', 'provides', 'obsoletes',
)
# Legal keyword arguments for the Extension constructor
extension_keywords = ('name', 'sources', 'include_dirs',
......
......@@ -106,6 +106,12 @@ Common commands: (see '--help-commands' for more)
"print the list of classifiers"),
('keywords', None,
"print the list of keywords"),
('provides', None,
"print the list of packages/modules provided"),
('requires', None,
"print the list of packages/modules required"),
('obsoletes', None,
"print the list of packages/modules made obsolete")
]
display_option_names = map(lambda x: translate_longopt(x[0]),
display_options)
......@@ -210,7 +216,6 @@ Common commands: (see '--help-commands' for more)
# distribution options.
if attrs:
# Pull out the set of command options and work on them
# specifically. Note that this order guarantees that aliased
# command options will override any supplied redundantly
......@@ -235,7 +240,9 @@ Common commands: (see '--help-commands' for more)
# Now work on the rest of the attributes. Any attribute that's
# not already defined is invalid!
for (key,val) in attrs.items():
if hasattr(self.metadata, key):
if hasattr(self.metadata, "set_" + key):
getattr(self.metadata, "set_" + key)(val)
elif hasattr(self.metadata, key):
setattr(self.metadata, key, val)
elif hasattr(self, key):
setattr(self, key, val)
......@@ -678,7 +685,8 @@ Common commands: (see '--help-commands' for more)
value = getattr(self.metadata, "get_"+opt)()
if opt in ['keywords', 'platforms']:
print string.join(value, ',')
elif opt == 'classifiers':
elif opt in ('classifiers', 'provides', 'requires',
'obsoletes'):
print string.join(value, '\n')
else:
print value
......@@ -1024,7 +1032,10 @@ class DistributionMetadata:
"license", "description", "long_description",
"keywords", "platforms", "fullname", "contact",
"contact_email", "license", "classifiers",
"download_url")
"download_url",
# PEP 314
"provides", "requires", "obsoletes",
)
def __init__ (self):
self.name = None
......@@ -1041,40 +1052,58 @@ class DistributionMetadata:
self.platforms = None
self.classifiers = None
self.download_url = None
# PEP 314
self.provides = None
self.requires = None
self.obsoletes = None
def write_pkg_info (self, base_dir):
"""Write the PKG-INFO file into the release tree.
"""
pkg_info = open( os.path.join(base_dir, 'PKG-INFO'), 'w')
pkg_info.write('Metadata-Version: 1.0\n')
pkg_info.write('Name: %s\n' % self.get_name() )
pkg_info.write('Version: %s\n' % self.get_version() )
pkg_info.write('Summary: %s\n' % self.get_description() )
pkg_info.write('Home-page: %s\n' % self.get_url() )
pkg_info.write('Author: %s\n' % self.get_contact() )
pkg_info.write('Author-email: %s\n' % self.get_contact_email() )
pkg_info.write('License: %s\n' % self.get_license() )
self.write_pkg_file(pkg_info)
pkg_info.close()
# write_pkg_info ()
def write_pkg_file (self, file):
"""Write the PKG-INFO format data to a file object.
"""
version = '1.0'
if self.provides or self.requires or self.obsoletes:
version = '1.1'
file.write('Metadata-Version: %s\n' % version)
file.write('Name: %s\n' % self.get_name() )
file.write('Version: %s\n' % self.get_version() )
file.write('Summary: %s\n' % self.get_description() )
file.write('Home-page: %s\n' % self.get_url() )
file.write('Author: %s\n' % self.get_contact() )
file.write('Author-email: %s\n' % self.get_contact_email() )
file.write('License: %s\n' % self.get_license() )
if self.download_url:
pkg_info.write('Download-URL: %s\n' % self.download_url)
file.write('Download-URL: %s\n' % self.download_url)
long_desc = rfc822_escape( self.get_long_description() )
pkg_info.write('Description: %s\n' % long_desc)
file.write('Description: %s\n' % long_desc)
keywords = string.join( self.get_keywords(), ',')
if keywords:
pkg_info.write('Keywords: %s\n' % keywords )
for platform in self.get_platforms():
pkg_info.write('Platform: %s\n' % platform )
file.write('Keywords: %s\n' % keywords )
for classifier in self.get_classifiers():
pkg_info.write('Classifier: %s\n' % classifier )
self._write_list(file, 'Platform', self.get_platforms())
self._write_list(file, 'Classifier', self.get_classifiers())
pkg_info.close()
# PEP 314
self._write_list(file, 'Requires', self.get_requires())
self._write_list(file, 'Provides', self.get_provides())
self._write_list(file, 'Obsoletes', self.get_obsoletes())
# write_pkg_info ()
def _write_list (self, file, name, values):
for value in values:
file.write('%s: %s\n' % (name, value))
# -- Metadata query methods ----------------------------------------
......@@ -1134,6 +1163,40 @@ class DistributionMetadata:
def get_download_url(self):
return self.download_url or "UNKNOWN"
# PEP 314
def get_requires(self):
return self.requires or []
def set_requires(self, value):
import distutils.versionpredicate
for v in value:
distutils.versionpredicate.VersionPredicate(v)
self.requires = value
def get_provides(self):
return self.provides or []
def set_provides(self, value):
value = [v.strip() for v in value]
for v in value:
import distutils.versionpredicate
ver = distutils.versionpredicate.check_provision(v)
if ver:
import distutils.version
sv = distutils.version.StrictVersion()
sv.parse(ver.strip()[1:-1])
self.provides = value
def get_obsoletes(self):
return self.obsoletes or []
def set_obsoletes(self, value):
import distutils.versionpredicate
for v in value:
distutils.versionpredicate.VersionPredicate(v)
self.obsoletes = value
# class DistributionMetadata
......
......@@ -4,6 +4,7 @@ import distutils.cmd
import distutils.dist
import os
import shutil
import StringIO
import sys
import tempfile
import unittest
......@@ -96,5 +97,93 @@ class DistributionTestCase(unittest.TestCase):
os.unlink(TESTFN)
class MetadataTestCase(unittest.TestCase):
def test_simple_metadata(self):
attrs = {"name": "package",
"version": "1.0"}
dist = distutils.dist.Distribution(attrs)
meta = self.format_metadata(dist)
self.assert_("Metadata-Version: 1.0" in meta)
self.assert_("provides:" not in meta.lower())
self.assert_("requires:" not in meta.lower())
self.assert_("obsoletes:" not in meta.lower())
def test_provides(self):
attrs = {"name": "package",
"version": "1.0",
"provides": ["package", "package.sub"]}
dist = distutils.dist.Distribution(attrs)
self.assertEqual(dist.metadata.get_provides(),
["package", "package.sub"])
self.assertEqual(dist.get_provides(),
["package", "package.sub"])
meta = self.format_metadata(dist)
self.assert_("Metadata-Version: 1.1" in meta)
self.assert_("requires:" not in meta.lower())
self.assert_("obsoletes:" not in meta.lower())
def test_provides_illegal(self):
self.assertRaises(ValueError,
distutils.dist.Distribution,
{"name": "package",
"version": "1.0",
"provides": ["my.pkg (splat)"]})
def test_requires(self):
attrs = {"name": "package",
"version": "1.0",
"requires": ["other", "another (==1.0)"]}
dist = distutils.dist.Distribution(attrs)
self.assertEqual(dist.metadata.get_requires(),
["other", "another (==1.0)"])
self.assertEqual(dist.get_requires(),
["other", "another (==1.0)"])
meta = self.format_metadata(dist)
self.assert_("Metadata-Version: 1.1" in meta)
self.assert_("provides:" not in meta.lower())
self.assert_("Requires: other" in meta)
self.assert_("Requires: another (==1.0)" in meta)
self.assert_("obsoletes:" not in meta.lower())
def test_requires_illegal(self):
self.assertRaises(ValueError,
distutils.dist.Distribution,
{"name": "package",
"version": "1.0",
"requires": ["my.pkg (splat)"]})
def test_obsoletes(self):
attrs = {"name": "package",
"version": "1.0",
"obsoletes": ["other", "another (<1.0)"]}
dist = distutils.dist.Distribution(attrs)
self.assertEqual(dist.metadata.get_obsoletes(),
["other", "another (<1.0)"])
self.assertEqual(dist.get_obsoletes(),
["other", "another (<1.0)"])
meta = self.format_metadata(dist)
self.assert_("Metadata-Version: 1.1" in meta)
self.assert_("provides:" not in meta.lower())
self.assert_("requires:" not in meta.lower())
self.assert_("Obsoletes: other" in meta)
self.assert_("Obsoletes: another (<1.0)" in meta)
def test_obsoletes_illegal(self):
self.assertRaises(ValueError,
distutils.dist.Distribution,
{"name": "package",
"version": "1.0",
"obsoletes": ["my.pkg (splat)"]})
def format_metadata(self, dist):
sio = StringIO.StringIO()
dist.metadata.write_pkg_file(sio)
return sio.getvalue()
def test_suite():
return unittest.makeSuite(DistributionTestCase)
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(DistributionTestCase))
suite.addTest(unittest.makeSuite(MetadataTestCase))
return suite
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