[Python-checkins] distutils2: now checking Requires-Python and Name
tarek.ziade
python-checkins at python.org
Fri Mar 12 19:32:53 CET 2010
tarek.ziade pushed 29e64afc676d to distutils2:
http://hg.python.org/distutils2/rev/29e64afc676d
changeset: 73:29e64afc676d
tag: tip
user: Tarek Ziade <tarek at ziade.org>
date: Fri Mar 12 13:26:01 2010 -0500
summary: now checking Requires-Python and Name
files: src/distutils2/metadata.py, src/distutils2/tests/test_metadata.py, src/distutils2/version.py
diff --git a/src/distutils2/metadata.py b/src/distutils2/metadata.py
--- a/src/distutils2/metadata.py
+++ b/src/distutils2/metadata.py
@@ -1,55 +1,9 @@
"""
-==================================================
Implementation of the Metadata for Python packages
-==================================================
-The file format is RFC 822 and there are currently three implementations.
-We only support reading/writing Metadata v1.0 or v1.2. If 1.1 is encountered
-1.1 extra fields will be ignored.
+Supports all Metadata formats (1.0, 1.1, 1.2).
+"""
-PEP 241 - Metadata v1.0
-=======================
-
-- Metadata-Version
-- Name
-- Version
-- Platform (multiple)
-- Summary
-- Description (optional)
-- Keywords (optional)
-- Home-page (optional)
-- Author (optional)
-- Author-email (optional)
-- License (optional)
-
-PEP 345 - Metadata v1.2
-=======================
-
-# XXX adding codename ? multiple email rfc232 ?
-
-- Metadata-Version
-- Name
-- Version
-- Platform (multiple)
-- Supported-Platform (multiple)
-- Summary
-- Description (optional) -- changed format
-- Keywords (optional)
-- Home-page (optional)
-- Download-URL
-- Author (optional)
-- Author-email (optional)
-- Maintainer (optional)
-- Maintainer-email (optional)
-- License (optional)
-- Classifier (multiple) -- see PEP 241
-- Requires-Python
-- Requires-External (multiple)
-- Requires-Dist (multiple)
-- Provides-Dist (multiple)
-- Obsoletes-Dist (multiple)
-
-"""
import re
import os
import sys
@@ -60,7 +14,8 @@
from distutils2.log import warn
from distutils2.util import rfc822_escape
-from distutils2.version import is_valid_predicate
+from distutils2.version import (is_valid_predicate, is_valid_version,
+ is_valid_versions)
from distutils2.errors import (MetadataConflictError,
MetadataUnrecognizedVersionError)
@@ -122,10 +77,11 @@
'Requires-External')
_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python',
- 'Obsoletes-Dist', 'Requires-External', 'Maintainer',
- 'Maintainer-email')
+ 'Obsoletes-Dist', 'Requires-External', 'Maintainer',
+ 'Maintainer-email')
_ALL_FIELDS = []
+
for field in _241_FIELDS + _314_FIELDS + _345_FIELDS:
if field in _ALL_FIELDS:
continue
@@ -164,37 +120,37 @@
return '1.2'
_ATTR2FIELD = {'metadata_version': 'Metadata-Version',
- 'name': 'Name',
- 'version': 'Version',
- 'platform': 'Platform',
- 'supported_platform': 'Supported-Platform',
- 'description': 'Summary',
- 'long_description': 'Description',
- 'keywords': 'Keywords',
- 'url': 'Home-page',
- 'author': 'Author',
- 'author_email': 'Author-email',
- 'maintainer': 'Maintainer',
- 'maintainer_email': 'Maintainer-email',
- 'licence': 'License',
- 'classifier': 'Classifier',
- 'download_url': 'Download-URL',
- 'obsoletes_dist': 'Obsoletes-Dist',
- 'provides_dist': 'Provides-Dist',
- 'requires_dist': 'Requires-Dist',
- 'requires_python': 'Requires-Python',
- 'requires_external': 'Requires-External',
- 'requires': 'Requires',
- 'provides': 'Provides',
- 'obsoletes': 'Obsoletes',
- }
+ 'name': 'Name',
+ 'version': 'Version',
+ 'platform': 'Platform',
+ 'supported_platform': 'Supported-Platform',
+ 'description': 'Summary',
+ 'long_description': 'Description',
+ 'keywords': 'Keywords',
+ 'url': 'Home-page',
+ 'author': 'Author',
+ 'author_email': 'Author-email',
+ 'maintainer': 'Maintainer',
+ 'maintainer_email': 'Maintainer-email',
+ 'licence': 'License',
+ 'classifier': 'Classifier',
+ 'download_url': 'Download-URL',
+ 'obsoletes_dist': 'Obsoletes-Dist',
+ 'provides_dist': 'Provides-Dist',
+ 'requires_dist': 'Requires-Dist',
+ 'requires_python': 'Requires-Python',
+ 'requires_external': 'Requires-External',
+ 'requires': 'Requires',
+ 'provides': 'Provides',
+ 'obsoletes': 'Obsoletes',
+ }
_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist')
-
+_VERSIONS_FIELDS = ('Requires-Python',)
+_VERSION_FIELDS = ('Version',)
_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes',
- 'Requires', 'Provides', 'Obsoletes-Dist',
- 'Provides-Dist', 'Requires-Dist', 'Requires-Python',
- 'Requires-External')
+ 'Requires', 'Provides', 'Obsoletes-Dist',
+ 'Provides-Dist', 'Requires-Dist', 'Requires-External')
_ELEMENTSFIELD = ('Keywords',)
@@ -347,23 +303,37 @@
"""Controls then sets a metadata field"""
name = self._convert_name(name)
- # XXX need to parse the Requires-Python value
- #
+ if (name in _ELEMENTSFIELD + ('Platform',) and
+ not isinstance(value, (list, tuple))):
+ if isinstance(value, str):
+ value = value.split(',')
+ else:
+ value = []
+ elif (name in _LISTFIELDS and
+ not isinstance(value, (list, tuple))):
+ if isinstance(value, str):
+ value = [value]
+ else:
+ value = None
+
if name in _PREDICATE_FIELDS and value is not None:
for v in value:
# check that the values are valid predicates
if not is_valid_predicate(v.split(';')[0]):
warn('"%s" is not a valid predicate' % v)
- if name in _LISTFIELDS + _ELEMENTSFIELD:
- if isinstance(value, str):
- value = value.split(',')
- elif name in _UNICODEFIELDS:
+ elif name in _VERSIONS_FIELDS and value is not None:
+ if not is_valid_versions(value):
+ warn('"%s" is not a valid predicate' % value)
+ elif name in _VERSION_FIELDS and value is not None:
+ if not is_valid_version(value):
+ warn('"%s" is not a valid version' % value)
+
+ if name in _UNICODEFIELDS:
value = self._encode_field(value)
if name == 'Description':
value = self._remove_line_prefix(value)
+
self._fields[name] = value
- # will trigger an error in case the user
- # tries to set incompatible versions fields
self._set_best_version()
def get(self, name):
diff --git a/src/distutils2/tests/test_metadata.py b/src/distutils2/tests/test_metadata.py
--- a/src/distutils2/tests/test_metadata.py
+++ b/src/distutils2/tests/test_metadata.py
@@ -137,11 +137,53 @@
def test_warnings(self):
metadata = DistributionMetadata()
- # this should raise a warning
- # XXX how to test this on 2.4 ?
- metadata['Requires-Dist'] = ['Funky (Groovie)']
+ # these should raise a warning
+ values = (('Requires-Dist', 'Funky (Groovie)'),
+ ('Requires-Python', '1-4'))
+ from distutils2 import metadata as m
+ old = m.warn
+ m.warns = 0
+ def _warn(*args):
+ m.warns += 1
+
+ m.warn = _warn
+
+ try:
+ for name, value in values:
+ metadata.set(name, value)
+ finally:
+ m.warn = old
+ res = m.warns
+ del m.warns
+
+ # we should have a certain amount of warnings
+ num_wanted = len(values)
+ self.assertEquals(num_wanted, res)
+
+ def test_multiple_predicates(self):
+ metadata = DistributionMetadata()
+
+ from distutils2 import metadata as m
+ old = m.warn
+ m.warns = 0
+
+ def _warn(*args):
+ m.warns += 1
+
+ # see for "3" instead of "3.0" ???
+ # its seems like the MINOR VERSION can be omitted
+ m.warn = _warn
+ try:
+ metadata['Requires-Python'] = '>=2.6, <3.0'
+ metadata['Requires-Dist'] = ['Foo (>=2.6, <3.0)']
+ finally:
+ m.warn = old
+ res = m.warns
+ del m.warns
+
+ self.assertEquals(res, 0)
def test_suite():
return unittest2.makeSuite(DistributionMetadataTestCase)
diff --git a/src/distutils2/version.py b/src/distutils2/version.py
--- a/src/distutils2/version.py
+++ b/src/distutils2/version.py
@@ -312,6 +312,7 @@
_PREDICATE = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)")
_VERSIONS = re.compile(r"^\s*\((.*)\)\s*$")
+_PLAIN_VERSIONS = re.compile(r"^\s*(.*)\s*$")
_SPLIT_CMP = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$")
def _split_predicate(predicate):
@@ -323,6 +324,7 @@
comp, version = match.groups()
return comp, NormalizedVersion(version)
+
class VersionPredicate(object):
"""Defines a predicate: ProjectName (>ver1,ver2, ..)"""
@@ -341,7 +343,6 @@
self.name, predicates = match.groups()
predicates = predicates.strip()
-
predicates = _VERSIONS.match(predicates)
if predicates is not None:
predicates = predicates.groups()[0]
@@ -359,6 +360,26 @@
return False
return True
+class Versions(VersionPredicate):
+ def __init__(self, predicate):
+ predicate = predicate.strip()
+ match = _PLAIN_VERSIONS.match(predicate)
+ if match is None:
+ raise ValueError('Bad predicate "%s"' % predicate)
+ self.name = None
+ predicates = match.groups()[0]
+ self.predicates = [_split_predicate(pred.strip())
+ for pred in predicates.split(',')]
+
+class Version(VersionPredicate):
+ def __init__(self, predicate):
+ predicate = predicate.strip()
+ match = _PLAIN_VERSIONS.match(predicate)
+ if match is None:
+ raise ValueError('Bad predicate "%s"' % predicate)
+ self.name = None
+ self.predicates = _split_predicate(match.groups()[0])
+
def is_valid_predicate(predicate):
try:
VersionPredicate(predicate)
@@ -367,3 +388,19 @@
else:
return True
+def is_valid_versions(predicate):
+ try:
+ Versions(predicate)
+ except (ValueError, IrrationalVersionError):
+ return False
+ else:
+ return True
+
+def is_valid_version(predicate):
+ try:
+ Version(predicate)
+ except (ValueError, IrrationalVersionError):
+ return False
+ else:
+ return True
+
--
Repository URL: http://hg.python.org/distutils2
More information about the Python-checkins
mailing list