jenkins-bot has submitted this change and it was merged.
Change subject: Log package versions ......................................................................
Log package versions
The version of major dependencies 'httplib2' and 'mwparserfromhell' shoud be written to the log, and included in the script version.py.
In verbose mode it is helpful to see what other major packages are being automatically loaded into the python environment, and their versions.
Move the online startup checks after the local checks.
Change-Id: Iae9f73b23ab1eb1a4acce46a690c0b4f9f9396a8 --- M pywikibot/bot.py M pywikibot/version.py M scripts/version.py 3 files changed, 132 insertions(+), 7 deletions(-)
Approvals: John Vandenberg: Looks good to me, but someone else must approve Merlijn van Deen: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/bot.py b/pywikibot/bot.py index 78e291a..6ab690f 100644 --- a/pywikibot/bot.py +++ b/pywikibot/bot.py @@ -19,7 +19,6 @@ # all output goes thru python std library "logging" module
import os -import os.path import sys import re import json @@ -268,22 +267,48 @@ except version.ParseError: exception()
- if config.log_pywiki_repo_version: - log(u'PYWIKI REPO VERSION: %s' % unicode(version.getversion_onlinerepo())) - - log(u'SITE VERSION: %s' % unicode(site.live_version())) - # system if hasattr(os, 'uname'): log(u'SYSTEM: %s' % unicode(os.uname()))
+ all_modules = sys.modules.keys() + + # These are the main dependencies of pywikibot. + check_package_list = ['httplib2', 'mwparserfromhell'] + + # report all imported packages + if config.verbose_output: + check_package_list += all_modules + + packages = version.package_versions(check_package_list) + + log(u'PACKAGES:') + for name in sorted(packages.keys()): + info = packages[name] + if 'path' not in info: + if 'type' in info: + info['path'] = '[' + info['type'] + ']' + else: + info['path'] = '[path unknown]' + if 'ver' not in info: + info['ver'] = '??' + if 'err' in info: + log(u' %(name)s: %(err)s' % info) + else: + log(u' %(name)s (%(path)s) = %(ver)s' % info) + # imported modules log(u'MODULES:') - for item in list(sys.modules.keys()): + for item in list(all_modules): ver = version.getfileversion('%s.py' % item.replace('.', '/')) if ver: log(u' %s' % ver)
+ if config.log_pywiki_repo_version: + log(u'PYWIKI REPO VERSION: %s' % unicode(version.getversion_onlinerepo())) + + log(u'SITE VERSION: %s' % unicode(site.live_version())) + # messages on bot discussion page? if site.logged_in(): if site.messages(): diff --git a/pywikibot/version.py b/pywikibot/version.py index 26bc0dc..e607c62 100644 --- a/pywikibot/version.py +++ b/pywikibot/version.py @@ -216,3 +216,101 @@ return u'%s %s %s' % (filename, __version__[5:-1][:7], mtime) else: return None + + +def package_versions(modules=None, builtins=False, standard_lib=None): + """ Retrieve package version information. + + When builtins or standard_lib are None, they will be included only + if a version was found in the package. + + @param modules: Modules to inspect + @type modules: list of strings + @param builtins: Include builtins + @type builtins: Boolean, or None for automatic selection + @param standard_lib: Include standard library packages + @type standard_lib: Boolean, or None for automatic selection + """ + import sys + + if not modules: + modules = sys.modules.keys() + + import distutils.sysconfig + std_lib_dir = distutils.sysconfig.get_python_lib(standard_lib=True) + + root_packages = set([key.split('.')[0] + for key in modules]) + + builtin_packages = set([name.split('.')[0] for name in root_packages + if name in sys.builtin_module_names or + '_' + name in sys.builtin_module_names]) + + # Improve performance by removing builtins from the list if possible. + if builtins is False: + root_packages = list(root_packages - builtin_packages) + + std_lib_packages = [] + + paths = {} + data = {} + + for name in root_packages: + try: + package = __import__(name, level=0) + except Exception as e: + data[name] = {'name': name, 'err': e} + continue + + info = {'package': package, 'name': name} + + if name in builtin_packages: + info['type'] = 'builtins' + + if '__file__' in package.__dict__: + # Determine if this file part is of the standard library. + if os.path.normcase(package.__file__).startswith( + os.path.normcase(std_lib_dir)): + std_lib_packages.append(name) + if standard_lib is False: + continue + info['type'] = 'standard libary' + + # Strip '__init__.py' from the filename. + path = package.__file__ + if '__init__.py' in path: + path = path[0:path.index('__init__.py')] + + info['path'] = path + assert(path not in paths) + paths[path] = name + + if '__version__' in package.__dict__: + info['ver'] = package.__version__ + elif name == 'mwlib': # mwlib 0.14.3 does not include a __init__.py + module = __import__(name + '._version', + fromlist=['_version'], level=0) + if '__version__' in module.__dict__: + info['ver'] = module.__version__ + path = module.__file__ + path = path[0:path.index('_version.')] + info['path'] = path + + # If builtins or standard_lib is None, + # only include package if a version was found. + if (builtins is None and name in builtin_packages) or \ + (standard_lib is None and name in std_lib_packages): + if 'ver' in info: + data[name] = info + else: + data[name] = info + + # Remove any sub-packages which were loaded with a different name. + # e.g. 'wikipedia_family.py' is loaded as 'wikipedia' + for path, name in paths.items(): + for other_path in set(paths) - set([path]): + if path.startswith(other_path) and not other_path.startswith(path): + del paths[path] + del data[name] + + return data diff --git a/scripts/version.py b/scripts/version.py index f341332..88b0f62 100755 --- a/scripts/version.py +++ b/scripts/version.py @@ -23,3 +23,5 @@ pywikibot.output(u'unicode test: triggers problem #3081100') else: pywikibot.output(u'unicode test: ok') + import httplib2 + pywikibot.output('httplib2 version: %s' % httplib2.__version__)
pywikibot-commits@lists.wikimedia.org