jenkins-bot has submitted this change and it was merged.
Change subject: Use setuptools for SVN support
......................................................................
Use setuptools for SVN support
setuptools supports SVN 1.6+, and is included in the
Windows py2.7 installer, and works for 1.8+ even if the
entries file is missing.
Update getversion to rotate through git, svn and nightly detectors
before falling back to alternative version algorithms.
Bug: T95075
Bug: T95077
Change-Id: I49cf168054dde5ed313970b4ac63de35d1d21d38
---
M pywikibot/version.py
1 file changed, 150 insertions(+), 34 deletions(-)
Approvals:
John Vandenberg: Looks good to me, but someone else must approve
XZise: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/version.py b/pywikibot/version.py
index 85f37a9..b3ba9eb 100644
--- a/pywikibot/version.py
+++ b/pywikibot/version.py
@@ -19,11 +19,26 @@
import subprocess
import codecs
+from warnings import warn
+
+try:
+ from setuptools import svn_utils
+except ImportError:
+ try:
+ from setuptools_svn import svn_utils
+ except ImportError as e:
+ svn_utils = e
+
import pywikibot
+
+from pywikibot import config2 as config
from pywikibot.tools import deprecated
-import pywikibot.config2 as config
+
+if sys.version_info[0] > 2:
+ basestring = (str, )
cache = None
+_logger = 'version'
class ParseError(Exception):
@@ -57,39 +72,61 @@
def getversiondict():
+ """Get version info for the package.
+
+ @return:
+ - tag (name for the repository),
+ - rev (current revision identifier),
+ - date (date of current revision),
+ - hash (git hash for the current revision)
+ @rtype: C{dict} of four C{str}
+ """
global cache
if cache:
return cache
- try:
- _program_dir = _get_program_dir()
- if os.path.isdir(os.path.join(_program_dir, '.svn')):
- (tag, rev, date, hsh) = getversion_svn(_program_dir)
- elif os.path.isdir(os.path.join(_program_dir, '../.svn')):
- (tag, rev, date, hsh) = getversion_svn(os.path.join(_program_dir,
'..'))
- else:
- (tag, rev, date, hsh) = getversion_git(_program_dir)
- except Exception:
+
+ _program_dir = _get_program_dir()
+ exceptions = {}
+
+ for vcs_func in (getversion_git,
+ getversion_svn_setuptools,
+ getversion_nightly,
+ getversion_svn,
+ getversion_package):
try:
- (tag, rev, date, hsh) = getversion_nightly()
- except Exception:
- try:
- hsh = get_module_version(pywikibot)
- date = get_module_mtime(pywikibot).timetuple()
+ (tag, rev, date, hsh) = vcs_func(_program_dir)
+ except Exception as e:
+ exceptions[vcs_func] = e
+ else:
+ break
+ else:
+ # nothing worked; version unknown (but suppress exceptions)
+ # the value is most likely '$Id' + '$', it means that
+ # pywikibot was imported without using version control at all.
+ tag, rev, date, hsh = (
+ '', '-1 (unknown)', '0 (unknown)',
'(unknown)')
- tag = 'pywikibot/__init__.py'
- rev = '-1 (unknown)'
- except:
- # nothing worked; version unknown (but suppress exceptions)
- # the value is most likely '$Id' + '$', it means that
- # pywikibot was imported without using version control at all.
- return dict(tag='', rev='-1 (unknown)', date='0
(unknown)',
- hsh='(unknown)')
+ # git and svn can silently fail, as it may be a nightly.
+ if getversion_package in exceptions:
+ warn('Unable to detect version; exceptions raised:\n%r'
+ % exceptions, UserWarning)
+ elif exceptions:
+ pywikibot.debug('version algorithm exceptions:\n%r'
+ % exceptions, _logger)
- datestring = time.strftime('%Y/%m/%d, %H:%M:%S', date)
+ if isinstance(date, basestring):
+ datestring = date
+ elif isinstance(date, time.struct_time):
+ datestring = time.strftime('%Y/%m/%d, %H:%M:%S', date)
+ else:
+ warn('Unable to detect package date', UserWarning)
+ datestring = '-2 (unknown)'
+
cache = dict(tag=tag, rev=rev, date=datestring, hsh=hsh)
return cache
+@deprecated('getversion_svn_setuptools')
def svn_rev_info(path):
"""Fetch information about the current revision of an Subversion
checkout.
@@ -98,9 +135,13 @@
- tag (name for the repository),
- rev (current Subversion revision identifier),
- date (date of current revision),
- @rtype: C{tuple} of 3 C{str}
+ @rtype: C{tuple} of two C{str} and a C{time.struct_time}
"""
+ if not os.path.isdir(os.path.join(path, '.svn')):
+ path = os.path.join(path, '..')
+
_program_dir = path
+
entries = open(os.path.join(_program_dir, '.svn/entries'))
version = entries.readline().strip()
# use sqlite table for new entries format
@@ -152,11 +193,43 @@
headers={'label': str(rev),
'user-agent': 'SVN/1.7.5 {pwb}'})
data = request.content
+
dom = xml.dom.minidom.parse(StringIO(data))
hsh = dom.getElementsByTagName("C:git-commit")[0].firstChild.nodeValue
- return hsh
+ date = dom.getElementsByTagName("S:date")[0].firstChild.nodeValue
+ date = time.strptime(date[:19], '%Y-%m-%dT%H:%M:%S')
+ return hsh, date
+def getversion_svn_setuptools(path=None):
+ """Get version info for a Subversion checkout using setuptools.
+
+ @param path: directory of the Subversion checkout
+ @return:
+ - tag (name for the repository),
+ - rev (current Subversion revision identifier),
+ - date (date of current revision),
+ - hash (git hash for the Subversion revision)
+ @rtype: C{tuple} of three C{str} and a C{time.struct_time}
+ """
+ if isinstance(svn_utils, Exception):
+ raise svn_utils
+ tag = 'pywikibot-core'
+ _program_dir = path or _get_program_dir()
+ svninfo = svn_utils.SvnInfo(_program_dir)
+ rev = svninfo.get_revision()
+ if not isinstance(rev, int):
+ raise TypeError('SvnInfo.get_revision() returned type %s' % type(rev))
+ if rev < 0:
+ raise ValueError('SvnInfo.get_revision() returned %d' % rev)
+ if rev == 0:
+ raise ParseError('SvnInfo: invalid workarea')
+ hsh, date = github_svn_rev2hash(tag, rev)
+ rev = 's%s' % rev
+ return (tag, rev, date, hsh)
+
+
+@deprecated('getversion_svn_setuptools')
def getversion_svn(path=None):
"""Get version info for a Subversion checkout.
@@ -166,11 +239,12 @@
- rev (current Subversion revision identifier),
- date (date of current revision),
- hash (git hash for the Subversion revision)
- @rtype: C{tuple} of 4 C{str}
+ @rtype: C{tuple} of three C{str} and a C{time.struct_time}
"""
_program_dir = path or _get_program_dir()
tag, rev, date = svn_rev_info(_program_dir)
- hsh = github_svn_rev2hash(tag, rev)
+ hsh, date2 = github_svn_rev2hash(tag, rev)
+ assert(date == date2)
rev = 's%s' % rev
if (not date or not tag or not rev) and not path:
raise ParseError
@@ -178,6 +252,16 @@
def getversion_git(path=None):
+ """Get version info for a Git clone.
+
+ @param path: directory of the Git checkout
+ @return:
+ - tag (name for the repository),
+ - rev (current revision identifier),
+ - date (date of current revision),
+ - hash (git hash for the current revision)
+ @rtype: C{tuple} of three C{str} and a C{time.struct_time}
+ """
_program_dir = path or _get_program_dir()
cmd = 'git'
try:
@@ -222,18 +306,50 @@
return (tag, rev, date, hsh)
-def getversion_nightly():
- data = open(os.path.join(os.path.split(__file__)[0], 'version'))
- tag = data.readline().strip()
- rev = data.readline().strip()
- date = time.strptime(data.readline()[:19], '%Y-%m-%dT%H:%M:%S')
- hsh = data.readline().strip()
+def getversion_nightly(path=None):
+ """Get version info for a nightly release.
+
+ @param path: directory of the uncompressed nightly.
+ @return:
+ - tag (name for the repository),
+ - rev (current revision identifier),
+ - date (date of current revision),
+ - hash (git hash for the current revision)
+ @rtype: C{tuple} of three C{str} and a C{time.struct_time}
+ """
+ if not path:
+ path = _get_program_dir()
+
+ with open(os.path.join(path, 'version')) as data:
+ (tag, rev, date, hsh) = data.readlines()
+
+ date = time.strptime(date[:19], '%Y-%m-%dT%H:%M:%S')
if not date or not tag or not rev:
raise ParseError
return (tag, rev, date, hsh)
+def getversion_package(path=None): # pylint: disable=unused-argument
+ """Get version info for an installed package.
+
+ @param path: Unused argument
+ @return:
+ - tag: 'pywikibot/__init__.py'
+ - rev: '-1 (unknown)'
+ - date (date the package was installed locally),
+ - hash (git hash for the current revision of 'pywikibot/__init__.py')
+ @rtype: C{tuple} of four C{str}
+ """
+ hsh = get_module_version(pywikibot)
+ date = get_module_mtime(pywikibot).timetuple()
+
+ tag = 'pywikibot/__init__.py'
+ rev = '-1 (unknown)'
+
+ return (tag, rev, date, hsh)
+
+
def getversion_onlinerepo(repo=None):
"""Retrieve current framework revision number from online repository.
--
To view, visit
https://gerrit.wikimedia.org/r/201931
To unsubscribe, visit
https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I49cf168054dde5ed313970b4ac63de35d1d21d38
Gerrit-PatchSet: 3
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: John Vandenberg <jayvdb(a)gmail.com>
Gerrit-Reviewer: Ladsgroup <ladsgroup(a)gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw(a)arctus.nl>
Gerrit-Reviewer: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: jenkins-bot <>