changeset: 1307:f453054a7d8b parent: 1304:932b3cea4285 user: Preston Holmes date: Tue Mar 13 20:26:28 2012 -0700 files: distutils2/database.py distutils2/tests/requires.txt distutils2/tests/test_util.py distutils2/util.py description: fix for 14294 diff -r 932b3cea4285 -r f453054a7d8b distutils2/database.py --- a/distutils2/database.py Tue Mar 13 17:01:28 2012 -0700 +++ b/distutils2/database.py Tue Mar 13 20:26:28 2012 -0700 @@ -15,6 +15,7 @@ from distutils2.errors import PackagingError from distutils2.version import suggest_normalized_version, VersionPredicate from distutils2.metadata import Metadata +from distutils2.util import parse_requires __all__ = [ @@ -300,11 +301,6 @@ """A :class:`distutils2.metadata.Metadata` instance loaded with the distribution's ``METADATA`` file.""" - _REQUIREMENT = re.compile( - r'(?P[-A-Za-z0-9_.]+)\s*' - r'(?P(?:<|<=|!=|==|>=|>)[-A-Za-z0-9_.]+)?\s*' - r'(?P(?:\s*,\s*(?:<|<=|!=|==|>=|>)[-A-Za-z0-9_.]+)*)\s*' - r'(?P\[.*\])?') def __init__(self, path): self.path = path @@ -314,20 +310,7 @@ self.version = self.metadata['Version'] return - # reused from Distribute's pkg_resources - def yield_lines(strs): - """Yield non-empty/non-comment lines of a ``basestring`` - or sequence""" - if isinstance(strs, basestring): - for s in strs.splitlines(): - s = s.strip() - # skip blank lines/comments - if s and not s.startswith('#'): - yield s - else: - for ss in strs: - for s in yield_lines(ss): - yield s + requires = None @@ -335,15 +318,8 @@ if os.path.isdir(path): meta_path = os.path.join(path, 'EGG-INFO', 'PKG-INFO') self.metadata = Metadata(path=meta_path) - try: - req_path = os.path.join(path, 'EGG-INFO', 'requires.txt') - fp = open(req_path, 'r') - try: - requires = fp.read() - finally: - fp.close() - except IOError: - requires = None + req_path = os.path.join(path, 'EGG-INFO', 'requires.txt') + requires = parse_requires(req_path) else: # FIXME handle the case where zipfile is not available zipf = zipimport.zipimporter(path) @@ -360,14 +336,8 @@ elif path.endswith('.egg-info'): if os.path.isdir(path): path = os.path.join(path, 'PKG-INFO') - try: - fp = open(os.path.join(path, 'requires.txt'), 'r') - try: - requires = fp.read() - finally: - fp.close() - except IOError: - requires = None + req_path = os.path.join(path, 'requires.txt') + requires = parse_requires(req_path) self.metadata = Metadata(path=path) self.name = self.metadata['Name'] self.version = self.metadata['Version'] @@ -383,40 +353,10 @@ if field in self.metadata: del self.metadata[field] - reqs = [] + - if requires is not None: - for line in yield_lines(requires): - if line.startswith('['): - logger.warning( - 'extensions in requires.txt are not supported ' - '(used by %r %s)', self.name, self.version) - break - else: - match = self._REQUIREMENT.match(line.strip()) - if not match: - # this happens when we encounter extras; since they - # are written at the end of the file we just exit - break - else: - if match.group('extras'): - msg = ('extra requirements are not supported ' - '(used by %r %s)', self.name, self.version) - logger.warning(msg, self.name) - name = match.group('name') - version = None - if match.group('first'): - version = match.group('first') - if match.group('rest'): - version += match.group('rest') - version = version.replace(' ', '') # trim spaces - if version is None: - reqs.append(name) - else: - reqs.append('%s (%s)' % (name, version)) - - if len(reqs)> 0: - self.metadata['Requires-Dist'] += reqs + if requires is not None and len(requires)>0: + self.metadata['Requires-Dist'] += requires if _cache_enabled: _cache_path_egg[self.path] = self diff -r 932b3cea4285 -r f453054a7d8b distutils2/tests/requires.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/distutils2/tests/requires.txt Tue Mar 13 20:26:28 2012 -0700 @@ -0,0 +1,15 @@ +setuptools +zope.browser +zope.component +zope.configuration +zope.contenttype>= 3.5 +zope.event +zope.exceptions +zope.i18n +zope.interface +zope.location +zope.proxy +zope.security + +[test] +zope.testing \ No newline at end of file diff -r 932b3cea4285 -r f453054a7d8b distutils2/tests/test_util.py --- a/distutils2/tests/test_util.py Tue Mar 13 17:01:28 2012 -0700 +++ b/distutils2/tests/test_util.py Tue Mar 13 20:26:28 2012 -0700 @@ -18,7 +18,8 @@ get_compiler_versions, _MAC_OS_X_LD_VERSION, byte_compile, find_packages, spawn, get_pypirc_path, generate_pypirc, read_pypirc, resolve_name, iglob, RICH_GLOB, egginfo_to_distinfo, is_setuptools, is_distutils, is_packaging, - get_install_method, cfg_to_args, generate_setup_py, encode_multipart) + get_install_method, cfg_to_args, generate_setup_py, encode_multipart, + parse_requires) from distutils2.tests import support, unittest from distutils2.tests.test_config import SETUP_CFG @@ -378,6 +379,15 @@ self.assertEqual(sorted(res), ['pkg1', 'pkg1.pkg3', 'pkg1.pkg3.pkg6', 'pkg5']) + def test_parse_requires(self): + req_file = os.path.join(os.path.dirname(__file__), 'requires.txt') + expected_requires = ['setuptools', 'zope.browser', 'zope.component', + 'zope.configuration', 'zope.contenttype', 'zope.event', + 'zope.exceptions', 'zope.i18n', 'zope.interface', + 'zope.location', 'zope.proxy', 'zope.security'] + requires = parse_requires(req_file) + self.assertEqual(requires, expected_requires) + def test_resolve_name(self): # test raw module name tmpdir = self.mkdtemp() diff -r 932b3cea4285 -r f453054a7d8b distutils2/util.py --- a/distutils2/util.py Tue Mar 13 17:01:28 2012 -0700 +++ b/distutils2/util.py Tue Mar 13 20:26:28 2012 -0700 @@ -25,6 +25,7 @@ from distutils2.errors import (PackagingPlatformError, PackagingFileError, PackagingExecError, InstallationException, PackagingInternalError) +from distutils2.metadata import Metadata from distutils2._backport import shutil, sysconfig __all__ = [ @@ -1172,6 +1173,71 @@ f.close() return record_path +def parse_requires(req_path): + """Takes the raw content of a requires.txt file and returns a list of requirements""" + + # reused from Distribute's pkg_resources + def yield_lines(strs): + """Yield non-empty/non-comment lines of a ``basestring`` + or sequence""" + if isinstance(strs, basestring): + for s in strs.splitlines(): + s = s.strip() + # skip blank lines/comments + if s and not s.startswith('#'): + yield s + else: + for ss in strs: + for s in yield_lines(ss): + yield s + + _REQUIREMENT = re.compile( + r'(?P[-A-Za-z0-9_.]+)\s*' + r'(?P(?:<|<=|!=|==|>=|>)[-A-Za-z0-9_.]+)?\s*' + r'(?P(?:\s*,\s*(?:<|<=|!=|==|>=|>)[-A-Za-z0-9_.]+)*)\s*' + r'(?P\[.*\])?') + + reqs = [] + try: + fp = open(req_path, 'r') + try: + requires = fp.read() + finally: + fp.close() + except IOError: + return None + + for line in yield_lines(requires): + if line.startswith('['): + logger.warning('extensions in requires.txt are not supported') + break + else: + match = _REQUIREMENT.match(line.strip()) + if not match: + # this happens when we encounter extras; since they + # are written at the end of the file we just exit + break + else: + if match.group('extras'): + # msg = ('extra requirements are not supported ' + # '(used by %r %s)', self.name, self.version) + msg = 'extra requirements are not supported' + logger.warning(msg) + name = match.group('name') + version = None + if match.group('first'): + version = match.group('first') + if match.group('rest'): + version += match.group('rest') + version = version.replace(' ', '') # trim spaces + if version is None: + reqs.append(name) + else: + reqs.append('%s (%s)' % (name, version)) + return reqs + + + def egginfo_to_distinfo(record_file, installer=_DEFAULT_INSTALLER, requested=False, remove_egginfo=False): @@ -1201,6 +1267,17 @@ metadata_path = distinfo['metadata_path'] logger.info('creating %s', metadata_path) shutil.copy2(distinfo['metadata'], metadata_path) + # add requirements and output metadata + requires = None + req_path = os.path.join(distinfo_dir, 'requires.txt') + requires = parse_requires(req_path) + if requires is not None: + # create a metadata instance to handle the reqs injection + metadata = Metadata(path=metadata_path) + metadata['Requires-Dist'] = requires + metadata.write(metadata_path) + + installer_path = distinfo['installer_path'] logger.info('creating %s', installer_path)

AltStyle によって変換されたページ (->オリジナル) /