diff options
author | Philip Thiem <ptthiem@gmail.com> | 2013-09-28 12:14:12 -0500 |
---|---|---|
committer | Philip Thiem <ptthiem@gmail.com> | 2013-09-28 12:14:12 -0500 |
commit | 30bb58f069cf1624f35cfbdb725e8e443ff64330 (patch) | |
tree | 394bf476bc9618fd89edab8249c5f945caaf3617 | |
parent | 8c645eb0c310e8ff4efe73849279ea391d25bced (diff) | |
download | external_python_setuptools-30bb58f069cf1624f35cfbdb725e8e443ff64330.tar.gz external_python_setuptools-30bb58f069cf1624f35cfbdb725e8e443ff64330.tar.bz2 external_python_setuptools-30bb58f069cf1624f35cfbdb725e8e443ff64330.zip |
Added a legacy fallback test
Added in code to after a deprecation warning parse the .svn files
Should also parse externals.
--HG--
extra : rebase_source : 9dd3bcf22cb56eb0826051f9e477f155e47cdbf6
-rw-r--r-- | setuptools.egg-info/entry_points.txt | 124 | ||||
-rw-r--r-- | setuptools.egg-info/requires.txt | 8 | ||||
-rw-r--r-- | setuptools/svn_utils.py | 240 | ||||
-rw-r--r-- | setuptools/tests/test_egg_info.py | 21 |
4 files changed, 310 insertions, 83 deletions
diff --git a/setuptools.egg-info/entry_points.txt b/setuptools.egg-info/entry_points.txt index d64b3c28..478fac7d 100644 --- a/setuptools.egg-info/entry_points.txt +++ b/setuptools.egg-info/entry_points.txt @@ -1,62 +1,62 @@ -[setuptools.installation] -eggsecutable = setuptools.command.easy_install:bootstrap - -[console_scripts] -easy_install = setuptools.command.easy_install:main -easy_install-3.3 = setuptools.command.easy_install:main - -[distutils.setup_keywords] -use_2to3 = setuptools.dist:assert_bool -namespace_packages = setuptools.dist:check_nsp -package_data = setuptools.dist:check_package_data -use_2to3_exclude_fixers = setuptools.dist:assert_string_list -dependency_links = setuptools.dist:assert_string_list -use_2to3_fixers = setuptools.dist:assert_string_list -test_suite = setuptools.dist:check_test_suite -exclude_package_data = setuptools.dist:check_package_data -extras_require = setuptools.dist:check_extras -install_requires = setuptools.dist:check_requirements -eager_resources = setuptools.dist:assert_string_list -include_package_data = setuptools.dist:assert_bool -packages = setuptools.dist:check_packages -entry_points = setuptools.dist:check_entry_points -zip_safe = setuptools.dist:assert_bool -tests_require = setuptools.dist:check_requirements -convert_2to3_doctests = setuptools.dist:assert_string_list -test_loader = setuptools.dist:check_importable - -[setuptools.file_finders] -svn_cvs = setuptools.command.sdist:_default_revctrl - -[egg_info.writers] -top_level.txt = setuptools.command.egg_info:write_toplevel_names -PKG-INFO = setuptools.command.egg_info:write_pkg_info -eager_resources.txt = setuptools.command.egg_info:overwrite_arg -namespace_packages.txt = setuptools.command.egg_info:overwrite_arg -depends.txt = setuptools.command.egg_info:warn_depends_obsolete -dependency_links.txt = setuptools.command.egg_info:overwrite_arg -entry_points.txt = setuptools.command.egg_info:write_entries -requires.txt = setuptools.command.egg_info:write_requirements - -[distutils.commands] -test = setuptools.command.test:test -bdist_wininst = setuptools.command.bdist_wininst:bdist_wininst -alias = setuptools.command.alias:alias -sdist = setuptools.command.sdist:sdist -develop = setuptools.command.develop:develop -bdist_egg = setuptools.command.bdist_egg:bdist_egg -setopt = setuptools.command.setopt:setopt -egg_info = setuptools.command.egg_info:egg_info -build_ext = setuptools.command.build_ext:build_ext -upload_docs = setuptools.command.upload_docs:upload_docs -easy_install = setuptools.command.easy_install:easy_install -install = setuptools.command.install:install -install_egg_info = setuptools.command.install_egg_info:install_egg_info -bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm -install_lib = setuptools.command.install_lib:install_lib -rotate = setuptools.command.rotate:rotate -saveopts = setuptools.command.saveopts:saveopts -install_scripts = setuptools.command.install_scripts:install_scripts -build_py = setuptools.command.build_py:build_py -register = setuptools.command.register:register - +[setuptools.installation]
+eggsecutable = setuptools.command.easy_install:bootstrap
+
+[console_scripts]
+easy_install = setuptools.command.easy_install:main
+easy_install-3.3 = setuptools.command.easy_install:main
+
+[distutils.setup_keywords]
+use_2to3 = setuptools.dist:assert_bool
+namespace_packages = setuptools.dist:check_nsp
+package_data = setuptools.dist:check_package_data
+use_2to3_exclude_fixers = setuptools.dist:assert_string_list
+dependency_links = setuptools.dist:assert_string_list
+use_2to3_fixers = setuptools.dist:assert_string_list
+test_suite = setuptools.dist:check_test_suite
+exclude_package_data = setuptools.dist:check_package_data
+extras_require = setuptools.dist:check_extras
+install_requires = setuptools.dist:check_requirements
+eager_resources = setuptools.dist:assert_string_list
+include_package_data = setuptools.dist:assert_bool
+packages = setuptools.dist:check_packages
+entry_points = setuptools.dist:check_entry_points
+zip_safe = setuptools.dist:assert_bool
+tests_require = setuptools.dist:check_requirements
+convert_2to3_doctests = setuptools.dist:assert_string_list
+test_loader = setuptools.dist:check_importable
+
+[setuptools.file_finders]
+svn_cvs = setuptools.command.sdist:_default_revctrl
+
+[egg_info.writers]
+top_level.txt = setuptools.command.egg_info:write_toplevel_names
+PKG-INFO = setuptools.command.egg_info:write_pkg_info
+eager_resources.txt = setuptools.command.egg_info:overwrite_arg
+namespace_packages.txt = setuptools.command.egg_info:overwrite_arg
+depends.txt = setuptools.command.egg_info:warn_depends_obsolete
+dependency_links.txt = setuptools.command.egg_info:overwrite_arg
+entry_points.txt = setuptools.command.egg_info:write_entries
+requires.txt = setuptools.command.egg_info:write_requirements
+
+[distutils.commands]
+test = setuptools.command.test:test
+bdist_wininst = setuptools.command.bdist_wininst:bdist_wininst
+alias = setuptools.command.alias:alias
+sdist = setuptools.command.sdist:sdist
+develop = setuptools.command.develop:develop
+bdist_egg = setuptools.command.bdist_egg:bdist_egg
+setopt = setuptools.command.setopt:setopt
+egg_info = setuptools.command.egg_info:egg_info
+build_ext = setuptools.command.build_ext:build_ext
+upload_docs = setuptools.command.upload_docs:upload_docs
+easy_install = setuptools.command.easy_install:easy_install
+install = setuptools.command.install:install
+install_egg_info = setuptools.command.install_egg_info:install_egg_info
+bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm
+install_lib = setuptools.command.install_lib:install_lib
+rotate = setuptools.command.rotate:rotate
+saveopts = setuptools.command.saveopts:saveopts
+install_scripts = setuptools.command.install_scripts:install_scripts
+build_py = setuptools.command.build_py:build_py
+register = setuptools.command.register:register
+
diff --git a/setuptools.egg-info/requires.txt b/setuptools.egg-info/requires.txt index 91d84d9c..221040f8 100644 --- a/setuptools.egg-info/requires.txt +++ b/setuptools.egg-info/requires.txt @@ -1,7 +1,7 @@ -[ssl:sys_platform=='win32'] -wincertstore==0.1 +[ssl:python_version in '2.4, 2.5'] +ssl==1.16 [ssl:sys_platform=='win32' and python_version=='2.4'] ctypes==1.0.2 @@ -9,5 +9,5 @@ ctypes==1.0.2 [certs] certifi==0.0.8 -[ssl:python_version in '2.4, 2.5'] -ssl==1.16
\ No newline at end of file +[ssl:sys_platform=='win32'] +wincertstore==0.1
\ No newline at end of file diff --git a/setuptools/svn_utils.py b/setuptools/svn_utils.py index 17b211d7..22b45cd7 100644 --- a/setuptools/svn_utils.py +++ b/setuptools/svn_utils.py @@ -6,7 +6,9 @@ import xml.dom.pulldom import shlex
import locale
import unicodedata
+import warnings
from setuptools.compat import unicode, bytes
+from xml.sax.saxutils import unescape
try:
import urlparse
@@ -23,6 +25,8 @@ from subprocess import Popen as _Popen, PIPE as _PIPE # http://bugs.python.org/issue8557
# http://stackoverflow.com/questions/5658622/
# python-subprocess-popen-environment-path
+
+
def _run_command(args, stdout=_PIPE, stderr=_PIPE):
#regarding the shell argument, see: http://bugs.python.org/issue8557
try:
@@ -63,10 +67,10 @@ def _get_xml_data(decoded_str): return data
-def joinpath(prefix, suffix):
+def joinpath(prefix, *suffix):
if not prefix or prefix == '.':
- return suffix
- return os.path.join(prefix, suffix)
+ return os.path.join(*suffix)
+ return os.path.join(prefix, *suffix)
def fsencode(path):
@@ -87,6 +91,7 @@ def fsencode(path): return path
+
def fsdecode(path):
"Path must be unicode or in file system encoding already"
encoding = sys.getfilesystemencoding()
@@ -98,6 +103,7 @@ def fsdecode(path): return unicodedata.normalize('NFC', path)
+
def consoledecode(text):
encoding = locale.getpreferredencoding()
return text.decode(encoding)
@@ -130,9 +136,7 @@ def parse_externals_xml(decoded_str, prefix=''): if event == 'START_ELEMENT' and node.nodeName == 'target':
doc.expandNode(node)
path = os.path.normpath(node.getAttribute('path'))
- log.warn('')
- log.warn('PRE: %s' % prefix)
- log.warn('PTH: %s' % path)
+
if os.path.normcase(path).startswith(prefix):
path = path[len(prefix)+1:]
@@ -154,7 +158,7 @@ def parse_external_prop(lines): """
externals = []
for line in lines.splitlines():
- line = line.lstrip() #there might be a "\ "
+ line = line.lstrip() # there might be a "\ "
if not line:
continue
@@ -178,6 +182,26 @@ def parse_external_prop(lines): return externals
+def parse_prop_file(filename, key):
+ found = False
+ f = open(filename, 'rt')
+ data = ''
+ try:
+ for line in iter(f.readline, ''): # can't use direct iter!
+ parts = line.split()
+ if len(parts) == 2:
+ kind, length = parts
+ data = f.read(int(length))
+ if kind == 'K' and data == key:
+ found = True
+ elif kind == 'V' and found:
+ break
+ finally:
+ f.close()
+
+ return data
+
+
class SvnInfo(object):
'''
Generic svn_info object. No has little knowledge of how to extract
@@ -203,14 +227,24 @@ class SvnInfo(object): @classmethod
def load(cls, dirname=''):
- code, data = _run_command(['svn', 'info', os.path.normpath(dirname)])
+ normdir = os.path.normpath(dirname)
+ code, data = _run_command(['svn', 'info', normdir])
+ has_svn = os.path.isdir(os.path.join(normdir, '.svn'))
svn_version = tuple(cls.get_svn_version().split('.'))
- base_svn_version = tuple(int(x) for x in svn_version[:2])
- if code and base_svn_version:
- #Not an SVN repository or compatible one
- return SvnInfo(dirname)
- elif base_svn_version < (1, 3):
- log.warn('Insufficent version of SVN found')
+
+ try:
+ base_svn_version = tuple(int(x) for x in svn_version[:2])
+ except ValueError:
+ base_svn_version = tuple()
+
+ if has_svn and (code or not base_svn_version
+ or base_svn_version < (1, 3)):
+ log.warn('Fallback onto .svn parsing')
+ warnings.warn(("No SVN 1.3+ command found: falling back "
+ "on pre 1.7 .svn parsing"), DeprecationWarning)
+ return SvnFileInfo(dirname)
+ elif not has_svn:
+ log.warn('Not SVN Repository')
return SvnInfo(dirname)
elif base_svn_version < (1, 5):
return Svn13Info(dirname)
@@ -259,7 +293,7 @@ class SvnInfo(object): Iterate over the non-deleted file entries in the repository path
'''
for item, kind in self.entries:
- if kind.lower()=='file':
+ if kind.lower() == 'file':
yield item
def iter_dirs(self, include_root=True):
@@ -269,7 +303,7 @@ class SvnInfo(object): if include_root:
yield self.path
for item, kind in self.entries:
- if kind.lower()=='dir':
+ if kind.lower() == 'dir':
yield item
def get_entries(self):
@@ -278,6 +312,7 @@ class SvnInfo(object): def get_externals(self):
return []
+
class Svn13Info(SvnInfo):
def get_entries(self):
code, data = _run_command(['svn', 'info', '-R', '--xml', self.path])
@@ -316,6 +351,73 @@ class Svn15Info(Svn13Info): return parse_externals_xml(lines, prefix=os.path.abspath(self.path))
+class SvnFileInfo(SvnInfo):
+
+ def __init__(self, path=''):
+ super(SvnFileInfo, self).__init__(path)
+ self._directories = None
+ self._revision = None
+
+ def _walk_svn(self, base):
+ entry_file = joinpath(base, '.svn', 'entries')
+ if os.path.isfile(entry_file):
+ entries = SVNEntriesFile.load(base)
+ yield (base, False, entries.parse_revision())
+ for path in entries.get_undeleted_records():
+ path = joinpath(base, path)
+ if os.path.isfile(path):
+ yield (path, True, None)
+ elif os.path.isdir(path):
+ for item in self._walk_svn(path):
+ yield item
+
+ def _build_entries(self):
+ dirs = list()
+ files = list()
+ rev = 0
+ for path, isfile, dir_rev in self._walk_svn(self.path):
+ if isfile:
+ files.append(path)
+ else:
+ dirs.append(path)
+ rev = max(rev, dir_rev)
+
+ self._directories = dirs
+ self._entries = files
+ self._revision = rev
+
+ def get_entries(self):
+ if self._entries is None:
+ self._build_entries()
+ return self._entries
+
+ def get_revision(self):
+ if self._revision is None:
+ self._build_entries()
+ return self._revision
+
+ def get_externals(self):
+ if self._directories is None:
+ self._build_entries()
+
+ prop_files = [['.svn', 'dir-prop-base'],
+ ['.svn', 'dir-props']]
+ externals = []
+
+ for dirname in self._directories:
+ prop_file = None
+ for rel_parts in prop_files:
+ filename = joinpath(dirname, *rel_parts)
+ if os.path.isfile(filename):
+ prop_file = filename
+
+ if prop_file is not None:
+ ext_prop = parse_prop_file(prop_file, 'svn:externals')
+ externals.extend(parse_external_prop(ext_prop))
+
+ return externals
+
+
def svn_finder(dirname=''):
#combined externals due to common interface
#combined externals and entries due to lack of dir_props in 1.7
@@ -328,6 +430,110 @@ def svn_finder(dirname=''): for sub_path in sub_info.iter_files():
yield fsencode(sub_path)
+
+class SVNEntriesFile(object):
+ def __init__(self, data):
+ self.data = data
+
+ @classmethod
+ def load(class_, base):
+ filename = os.path.join(base, '.svn', 'entries')
+ f = open(filename)
+ try:
+ result = SVNEntriesFile.read(f)
+ finally:
+ f.close()
+ return result
+
+ @classmethod
+ def read(class_, fileobj):
+ data = fileobj.read()
+ is_xml = data.startswith('<?xml')
+ class_ = [SVNEntriesFileText, SVNEntriesFileXML][is_xml]
+ return class_(data)
+
+ def parse_revision(self):
+ all_revs = self.parse_revision_numbers() + [0]
+ return max(all_revs)
+
+
+class SVNEntriesFileText(SVNEntriesFile):
+ known_svn_versions = {
+ '1.4.x': 8,
+ '1.5.x': 9,
+ '1.6.x': 10,
+ }
+
+ def __get_cached_sections(self):
+ return self.sections
+
+ def get_sections(self):
+ SECTION_DIVIDER = '\f\n'
+ sections = self.data.split(SECTION_DIVIDER)
+ sections = [x for x in map(str.splitlines, sections)]
+ try:
+ # remove the SVN version number from the first line
+ svn_version = int(sections[0].pop(0))
+ if not svn_version in self.known_svn_versions.values():
+ log.warn("Unknown subversion verson %d", svn_version)
+ except ValueError:
+ return
+ self.sections = sections
+ self.get_sections = self.__get_cached_sections
+ return self.sections
+
+ def is_valid(self):
+ return bool(self.get_sections())
+
+ def get_url(self):
+ return self.get_sections()[0][4]
+
+ def parse_revision_numbers(self):
+ revision_line_number = 9
+ rev_numbers = [
+ int(section[revision_line_number])
+ for section in self.get_sections()
+ if (len(section) > revision_line_number
+ and section[revision_line_number])
+ ]
+ return rev_numbers
+
+ def get_undeleted_records(self):
+ undeleted = lambda s: s and s[0] and (len(s) < 6 or s[5] != 'delete')
+ result = [
+ section[0]
+ for section in self.get_sections()
+ if undeleted(section)
+ ]
+ return result
+
+
+class SVNEntriesFileXML(SVNEntriesFile):
+ def is_valid(self):
+ return True
+
+ def get_url(self):
+ "Get repository URL"
+ urlre = re.compile('url="([^"]+)"')
+ return urlre.search(self.data).group(1)
+
+ def parse_revision_numbers(self):
+ revre = re.compile(r'committed-rev="(\d+)"')
+ return [
+ int(m.group(1))
+ for m in revre.finditer(self.data)
+ ]
+
+ def get_undeleted_records(self):
+ entries_pattern = \
+ re.compile(r'name="([^"]+)"(?![^>]+deleted="true")', re.I)
+ results = [
+ unescape(match.group(1))
+ for match in entries_pattern.finditer(self.data)
+ ]
+ return results
+
+
if __name__ == '__main__':
for name in svn_finder(sys.argv[1]):
- print(name)
\ No newline at end of file + print(name)
diff --git a/setuptools/tests/test_egg_info.py b/setuptools/tests/test_egg_info.py index 95667b69..7abafd71 100644 --- a/setuptools/tests/test_egg_info.py +++ b/setuptools/tests/test_egg_info.py @@ -48,6 +48,27 @@ class TestEggInfo(unittest.TestCase): rev = egg_info.egg_info.get_svn_revision() self.assertEqual(rev, '89000') + def test_version_10_format_legacy_parser(self): + """ + """ + path_variable = None + for env in os.environ: + if env.lower() == 'path': + path_variable = env + + if path_variable is None: + self.skipTest('Cannot figure out how to modify path') + + old_path = os.environ[path_variable] + os.environ[path_variable] = '' + try: + self._write_entries(ENTRIES_V10) + rev = egg_info.egg_info.get_svn_revision() + finally: + os.environ[path_variable] = old_path + + self.assertEqual(rev, '89000') + def test_suite(): return unittest.defaultTestLoader.loadTestsFromName(__name__) |