jenkins-bot has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/463775 )
Change subject: [cleanup] remove pre mw 1.14 code ......................................................................
[cleanup] remove pre mw 1.14 code
Lowest supported mw version of pywikibot core release is 1.14. Remove old code stuff for previous releases.
Refer https://www.mediawiki.org/wiki/Special:Code/pywikipedia/6185
Also simplify Namespace initialzer and remove duplicate alias assignment and reduce code complexity from C16 to B9
Bug: T106121 Change-Id: If85dec45e51d453fac6cb285b8d0c35b22c2bdcc --- M pywikibot/data/api.py M pywikibot/page.py M pywikibot/site.py M tests/api_tests.py M tests/dry_api_tests.py M tests/dry_site_tests.py M tests/namespace_tests.py 7 files changed, 51 insertions(+), 311 deletions(-)
Approvals: Mpaa: Looks good to me, approved jenkins-bot: Verified
diff --git a/pywikibot/data/api.py b/pywikibot/data/api.py index de32f17..bae4e87 100644 --- a/pywikibot/data/api.py +++ b/pywikibot/data/api.py @@ -168,10 +168,6 @@
Provides cache aware fetching of parameter information.
- Full support for MW 1.12+, when 'paraminfo' was introduced to the API. - Partially supports MW 1.11, using data extracted from API 'help'. - MW 1.10 not supported as module prefixes are not extracted from API 'help'. - It does not support the format modules. """
@@ -239,7 +235,7 @@ mw_ver = self.site.mw_version
if mw_ver < '1.15': - self._parse_help(mw_ver) + self._parse_help()
# The paraminfo api deprecated the old request syntax of # querymodules='info'; to avoid warnings sites with 1.25wmf4+ @@ -300,11 +296,8 @@ 'parameters': self._paraminfo['query']['parameters'] }
- def _parse_help(self, _mw_ver): - """Emulate paraminfo data using help.""" - # 1.14 paraminfo 'main' module doesnt exist. - # paraminfo only exists 1.12+. - + def _parse_help(self): + """Emulate paraminfo['main'] data using help for mw 1.14.""" # Request need ParamInfo to determine use_get request = self.site._request(expiry=config.API_config_expiry, use_get=True, @@ -353,181 +346,6 @@ ], }
- if _mw_ver >= '1.12': - return - - query_help_list_prefix = "Values (separate with '|'): " - - start = help_text.find('Which properties to get') - start = help_text.find(query_help_list_prefix, start) - start += len(query_help_list_prefix) - end = help_text.find('\n', start) - - prop_modules = help_text[start:end].split(', ') - - start = help_text.find('Which lists to get') - start = help_text.find(query_help_list_prefix, start) - start += len(query_help_list_prefix) - end = help_text.find('\n', start) - - list_modules = help_text[start:end].split(', ') - - start = help_text.find('Which meta data to get') - start = help_text.find(query_help_list_prefix, start) - start += len(query_help_list_prefix) - end = help_text.find('\n', start) - - meta_modules = help_text[start:end].split(', ') - - start = help_text.find('Use the output of a list as the input') - start = help_text.find('One value: ', start) - start += len('One value: ') - end = help_text.find('\n', start) - - gen_modules = help_text[start:end].split(', ') - - self._paraminfo['paraminfo'] = { - 'name': 'paraminfo', - 'path': 'paraminfo', - 'classname': 'ApiParamInfo', - 'prefix': '', - 'readrights': '', - 'helpurls': [], - 'parameters': [ - { - 'name': 'querymodules', - 'type': (prop_modules + list_modules - + meta_modules + gen_modules), - 'limit': 50, - }, - ], - } - - self._paraminfo['query'] = { - 'name': 'query', - 'path': 'query', - 'classname': 'ApiQuery', - 'prefix': '', - 'readrights': '', - 'helpurls': [], - 'parameters': [ - { - 'name': 'prop', - 'type': prop_modules, - 'submodules': '', - }, - { - 'name': 'list', - 'type': list_modules, - 'submodules': '', - }, - { - 'name': 'meta', - 'type': meta_modules, - 'submodules': '', - }, - { - 'name': 'generator', - 'type': gen_modules, - }, - ], - } - # Converted entries added, now treat them like they have been fetched - self._generate_submodules(['main', 'query']) - - # TODO: rewrite 'help' parser to determine prefix from the parameter - # names, as API 1.10 help does not include prefix on the first line. - - for mod_type in ['action', 'prop', 'list', 'meta', 'generator']: - if mod_type == 'action': - submodules = self.parameter('main', mod_type)['type'] - path_prefix = '' - else: - submodules = self.parameter('query', mod_type) - submodules = submodules['type'] - path_prefix = 'query+' - - for submodule in submodules: - mod_begin_string = '* %s=%s' % (mod_type, submodule) - start = help_text.find(mod_begin_string) - assert(start) - start += len(mod_begin_string) - end = help_text.find('\n*', start) - - if help_text[start + 1] == '(' and help_text[start + 4] == ')': - prefix = help_text[start + 2:start + 4] - else: - prefix = '' - - path = path_prefix + submodule - - # query is added above; some query modules appear as both - # prop and generator, and the generator doesnt have a - # prefix in the help. - if path not in self._paraminfo: - php_class = 'Api' - if mod_type == 'action': - php_class += 'Query' - # This doesnt correctly derive PHP class names where there - # are additional uppercase letters in the class name. - php_class += submodule.title() - - self._paraminfo[path] = { - 'name': submodule, - 'path': path, - 'classname': php_class, - 'prefix': prefix, - 'readrights': '', - 'helpurls': [], - 'parameters': [], - } - - if not prefix: - continue - - params = {} - - # Check existence of parameters used frequently by pywikibot. - # TODO: for each parameter, parse list of values ('type') - if prefix + 'limit' in help_text: - params['limit'] = { - 'name': 'limit', - 'type': 'limit', - 'max': 50, - } - - if prefix + 'namespace' in help_text: - params['namespace'] = { - 'name': 'namespace', - 'type': 'namespace', - } - if not submodule.startswith('all'): - params['namespace']['multi'] = '' - - for param_name in ['token', 'prop', 'type', 'show']: - if prefix + param_name in help_text: - params[param_name] = { - 'name': param_name, - 'type': [], - 'multi': '', - } - - self._paraminfo[path]['parameters'] = params.values() - if (help_text.find('\n\nThis module only accepts POST ' - 'requests.\n', start) < end): - self._paraminfo[path]['mustbeposted'] = '' - # All actions which must be POSTed are write actions except for - # login. Because Request checks if the user is logged in when - # doing a write action the check would always fail on login. - # Purge is the only action which isn't POSTed but actually does - # require writerights. This was checked with the data from - # 1.25wmf22 on en.wikipedia.org. - if ('mustbeposted' in self._paraminfo[path] - and path != 'login') or path == 'purge': - self._paraminfo[path]['writerights'] = '' - - self._emulate_pageset() - @staticmethod def _modules_to_set(modules): """Return modules as a set. @@ -592,13 +410,6 @@
assert 'query' in self._modules or 'paraminfo' not in self._paraminfo
- if self.site.mw_version < '1.12': - # When the help is parsed, all paraminfo should already be loaded - # and the caller is responsible for detecting missing modules. - pywikibot.log('ParamInfo did not detect modules: %s' - % modules, _logger=_logger) - return - # If something went wrong in a batch it can add each module to the # batch and the generator will on the next iteration yield each module # separately diff --git a/pywikibot/page.py b/pywikibot/page.py index d2be85c..657bbf8 100644 --- a/pywikibot/page.py +++ b/pywikibot/page.py @@ -2954,7 +2954,6 @@ if total == 0: return
- @need_version('1.13') def isEmptyCategory(self): """ Return True if category has no members (including subcategories). @@ -2964,7 +2963,6 @@ ci = self.categoryinfo return sum(ci[k] for k in ['files', 'pages', 'subcats']) == 0
- @need_version('1.11') def isHiddenCategory(self): """ Return True if the category is hidden. diff --git a/pywikibot/site.py b/pywikibot/site.py index bf135f5..0a2c5c6 100644 --- a/pywikibot/site.py +++ b/pywikibot/site.py @@ -159,10 +159,7 @@ namespace alias*]
If the canonical_name is not provided for a namespace between -2 - and 15, the MediaWiki 1.14+ built-in names are used. - Enable use_image_name to use built-in names from MediaWiki 1.13 - and earlier as the details. - + and 15, the MediaWiki built-in names are used. Image and File are aliases of each other by default.
If only one of canonical_name and custom_name are available, both @@ -212,8 +209,9 @@ 15: 'Category talk', }
+ @deprecated_args(use_image_name=None) def __init__(self, id, canonical_name=None, custom_name=None, - aliases=None, use_image_name=False, **kwargs): + aliases=None, **kwargs): """Initializer.
@param custom_name: Name defined in server LocalSettings.php @@ -222,27 +220,9 @@ @type canonical_name: str @param aliases: Aliases @type aliases: list of unicode - @param use_image_name: Use 'Image' as default canonical - for 'File' namespace - @param use_image_name: bool - """ self.id = id - - if aliases is None: - self.aliases = [] - else: - self.aliases = aliases - - if not canonical_name and id in self.canonical_namespaces: - if use_image_name: - if id == 6: - canonical_name = 'Image' - elif id == 7: - canonical_name = 'Image talk' - - if not canonical_name: - canonical_name = self.canonical_namespaces[id] + canonical_name = canonical_name or self.canonical_namespaces.get(id)
assert custom_name is not None or canonical_name is not None, \ 'Namespace needs to have at least one name' @@ -252,19 +232,15 @@ self.canonical_name = canonical_name \ if canonical_name is not None else custom_name
- if not aliases: - if id in (6, 7): - if use_image_name: - alias = 'File' - else: - alias = 'Image' - if id == 7: - alias += ' talk' - self.aliases = [alias] - else: - self.aliases = [] - else: + if aliases: self.aliases = aliases + elif id in (6, 7): + alias = 'Image' + if id == 7: + alias += ' talk' + self.aliases = [alias] + else: + self.aliases = []
for key, value in kwargs.items(): setattr(self, key, value) @@ -422,10 +398,16 @@ return default_case
@classmethod - def builtin_namespaces(cls, use_image_name=False, case='first-letter'): + @deprecated_args(use_image_name=None) + def builtin_namespaces(cls, use_image_name=None, case='first-letter'): """Return a dict of the builtin namespaces.""" - return {i: cls(i, use_image_name=use_image_name, - case=cls.default_case(i, case)) for i in range(-2, 16)} + if use_image_name is not None: + issue_deprecation_warning( + 'positional argument of "use_image_name"', None, 3, + DeprecationWarning, since='20181015') + + return {i: cls(i, case=cls.default_case(i, case)) + for i in range(-2, 16)}
@staticmethod def normalize_name(name): @@ -1032,9 +1014,7 @@
def _build_namespaces(self): """Create default namespaces.""" - use_image_name = MediaWikiVersion( - self.version()) < MediaWikiVersion('1.14') - return Namespace.builtin_namespaces(use_image_name) + return Namespace.builtin_namespaces()
@property def namespaces(self): @@ -2530,7 +2510,6 @@ return msgs['comma-separator'].join( args[:-2] + [concat.join(args[-2:])])
- @need_version('1.12') @deprecated_args(string='text') def expand_text(self, text, title=None, includecomments=None): """Parse the given text for preprocessing and rendering. @@ -2603,7 +2582,6 @@ getcurrenttime = redirect_func(server_time, old_name='getcurrenttime', class_name='APISite', since='20141225')
- @need_version('1.14') def getmagicwords(self, word): """Return list of localized "word" magic words for the site.""" if not hasattr(self, '_magicwords'): @@ -2660,12 +2638,6 @@ def _build_namespaces(self): _namespaces = {}
- # In MW 1.14, API siprop 'namespaces' added 'canonical', - # and Image became File with Image as an alias. - # For versions lower than 1.14, APISite needs to override - # the defaults defined in Namespace. - is_mw114 = self.mw_version >= '1.14' - for nsdata in self.siteinfo.get('namespaces', cache=False).values(): ns = nsdata.pop('id') custom_name = None @@ -2675,8 +2647,7 @@ custom_name = canonical_name else: custom_name = nsdata.pop('*') - if is_mw114: - canonical_name = nsdata.pop('canonical') + canonical_name = nsdata.pop('canonical')
if 'content' not in nsdata: # mw < 1.16 nsdata['content'] = ns == 0 @@ -2688,9 +2659,7 @@ assert default_case == nsdata['case'], \ 'Default case is not consistent'
- namespace = Namespace(ns, canonical_name, custom_name, - use_image_name=not is_mw114, - **nsdata) + namespace = Namespace(ns, canonical_name, custom_name, **nsdata) _namespaces[ns] = namespace
for item in self.siteinfo.get('namespacealiases'): @@ -2706,7 +2675,6 @@
return _namespaces
- @need_version('1.14') @deprecated('has_extension', since='20140819') def hasExtension(self, name, unknown=None): """Determine whether extension `name` is loaded. @@ -2729,7 +2697,6 @@ return True return False
- @need_version('1.14') def has_extension(self, name): """Determine whether extension `name` is loaded.
@@ -3566,7 +3533,7 @@ # patrol token require special handling. # TODO: try to catch exceptions? if 'patrol' in valid_tokens: - if '1.14' <= mw_ver < '1.17': + if mw_ver < '1.17': if 'edit' in user_tokens: user_tokens['patrol'] = user_tokens['edit'] else: @@ -3947,10 +3914,7 @@ if isinstance(member_type, basestring): member_type = {member_type}
- if member_type and (sortby == 'timestamp' or self.mw_version < '1.12'): - # Retrofit cmtype/member_type, available on MW API 1.12+, - # to use namespaces available on earlier versions. - + if member_type and sortby == 'timestamp': # Covert namespaces to a known type namespaces = set(self.namespaces.resolve(namespaces or []))
@@ -4840,10 +4804,7 @@ issue_deprecation_warning("where='titles'", "where='title'", 2, since='20160224') - if self.mw_version < '1.11': - where = 'titles' - else: - where = 'title' + where = 'title' if not namespaces and namespaces != 0: namespaces = [ns_id for ns_id in self.namespaces if ns_id >= 0] srgen = self._generator(api.PageGenerator, type_arg='search', @@ -5887,7 +5848,6 @@
yield result['patrol']
- @need_version('1.12') @must_be(group='sysop') def blockuser(self, user, expiry, reason, anononly=True, nocreate=True, autoblock=True, noemail=False, reblock=False): @@ -5939,7 +5899,6 @@ data = req.submit() return data
- @need_version('1.12') @must_be(group='sysop') def unblockuser(self, user, reason=None): """ diff --git a/tests/api_tests.py b/tests/api_tests.py index cd68929..2f99b16 100644 --- a/tests/api_tests.py +++ b/tests/api_tests.py @@ -194,9 +194,7 @@
self.assertIn('main', pi._paraminfo) self.assertIn('paraminfo', pi._paraminfo) - if self.site.mw_version >= '1.12': - self.assertEqual(len(pi), - len(pi.preloaded_modules)) + self.assertEqual(len(pi), len(pi.preloaded_modules))
self.assertIn('info', pi.query_modules) self.assertIn('login', pi._action_modules) @@ -234,9 +232,6 @@ self.assertIn('paraminfo', pi._paraminfo) self.assertIn('pageset', pi._paraminfo)
- if self.site.mw_version < '1.12': - return - if 'query' in pi.preloaded_modules: self.assertIn('query', pi._paraminfo) self.assertEqual(len(pi), 4) @@ -281,9 +276,7 @@
self.assertIn('main', pi._paraminfo) self.assertIn('paraminfo', pi._paraminfo) - if self.site.mw_version >= '1.12': - self.assertEqual(len(pi), - 1 + len(pi.preloaded_modules)) + self.assertEqual(len(pi), 1 + len(pi.preloaded_modules))
self.assertEqual(pi['info']['prefix'], 'in')
@@ -295,9 +288,6 @@
self.assertIsInstance(param['type'], list)
- if self.site.mw_version < '1.12': - return - self.assertIn('protection', param['type'])
def test_with_module_revisions(self): @@ -310,9 +300,7 @@
self.assertIn('main', pi._paraminfo) self.assertIn('paraminfo', pi._paraminfo) - if self.site.mw_version >= '1.12': - self.assertEqual(len(pi), - 1 + len(pi.preloaded_modules)) + self.assertEqual(len(pi), 1 + len(pi.preloaded_modules))
self.assertEqual(pi['revisions']['prefix'], 'rv')
@@ -324,9 +312,6 @@
self.assertIsInstance(param['type'], list)
- if self.site.mw_version < '1.12': - return - self.assertIn('user', param['type'])
def test_multiple_modules(self): @@ -341,11 +326,7 @@ self.assertIn('main', pi._paraminfo) self.assertIn('paraminfo', pi._paraminfo)
- if self.site.mw_version < '1.12': - return - - self.assertEqual(len(pi), - 2 + len(pi.preloaded_modules)) + self.assertEqual(len(pi), 2 + len(pi.preloaded_modules))
def test_with_invalid_module(self): """Test requesting different kind of invalid modules.""" @@ -364,11 +345,7 @@ self.assertIn('main', pi._paraminfo) self.assertIn('paraminfo', pi._paraminfo)
- if self.site.mw_version < '1.12': - return - - self.assertEqual(len(pi), - len(pi.preloaded_modules)) + self.assertEqual(len(pi), len(pi.preloaded_modules))
def test_submodules(self): """Test another module apart from query having submodules.""" @@ -467,9 +444,7 @@ self.assertIn('main', pi._paraminfo) self.assertIn('paraminfo', pi._paraminfo)
- if self.site.mw_version >= '1.12': - self.assertEqual(len(pi), - 1 + len(pi.preloaded_modules)) + self.assertEqual(len(pi), 1 + len(pi.preloaded_modules))
self.assertIn('query+revisions', pi.prefix_map)
diff --git a/tests/dry_api_tests.py b/tests/dry_api_tests.py index f93a98c..285637d 100644 --- a/tests/dry_api_tests.py +++ b/tests/dry_api_tests.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """API tests which do not interact with a site.""" # -# (C) Pywikibot team, 2012-2018 +# (C) Pywikibot team, 2012-2019 # # Distributed under the terms of the MIT license. # @@ -155,7 +155,7 @@ self._siteinfo = DummySiteinfo({'case': 'first-letter'})
def version(self): - return '1.13' # pre 1.14 + return '1.14' # lowest supported release
def protocol(self): return 'http' diff --git a/tests/dry_site_tests.py b/tests/dry_site_tests.py index bc240e4..b49aadc 100644 --- a/tests/dry_site_tests.py +++ b/tests/dry_site_tests.py @@ -140,7 +140,7 @@ self._logged_in_as = None self.obsolete = False super(TestMustBe, self).setUp() - self.version = lambda: '1.13' # pre 1.14 + self.version = lambda: '1.14' # lowest supported release
def login(self, sysop): """Fake the log in and just store who logged in.""" @@ -213,43 +213,43 @@ def setUp(self): """Set up test method.""" super(TestNeedVersion, self).setUp() - self.version = lambda: '1.13' + self.version = lambda: '1.23'
- @need_version('1.14') + @need_version('1.24') def too_new(self): """Method which is to new.""" return True
- @need_version('1.13') + @need_version('1.23') def old_enough(self): """Method which is as new as the server.""" return True
- @need_version('1.12') + @need_version('1.22') def older(self): """Method which is old enough.""" return True
- @need_version('1.14') + @need_version('1.24') @deprecated def deprecated_unavailable_method(self): """Method which is to new and then deprecated.""" return True
@deprecated - @need_version('1.14') + @need_version('1.24') def deprecated_unavailable_method2(self): """Method which is deprecated first and then to new.""" return True
- @need_version('1.12') + @need_version('1.22') @deprecated def deprecated_available_method(self): """Method which is old enough and then deprecated.""" return True
@deprecated - @need_version('1.12') + @need_version('1.22') def deprecated_available_method2(self): """Method which is deprecated first and then old enough.""" return True diff --git a/tests/namespace_tests.py b/tests/namespace_tests.py index 08f9c86..e8e364f 100644 --- a/tests/namespace_tests.py +++ b/tests/namespace_tests.py @@ -19,7 +19,8 @@ UnicodeType as unicode, )
-from tests.aspects import unittest, TestCase, AutoDeprecationTestCase +from tests.aspects import (CapturingTestCase, DeprecationTestCase, + TestCase, unittest)
# Default namespaces which should work in any MW wiki _base_builtin_ns = { @@ -230,7 +231,7 @@ self.assertEqual(a, b)
-class TestNamespaceDictDeprecated(AutoDeprecationTestCase): +class TestNamespaceDictDeprecated(CapturingTestCase, DeprecationTestCase):
"""Test static/classmethods in Namespace replaced by NamespacesDict."""
@@ -316,17 +317,13 @@
def test_lookup_name(self): """Test Namespace.lookup_name.""" - file_nses = Namespace.builtin_namespaces(use_image_name=False) - image_nses = Namespace.builtin_namespaces(use_image_name=True) + file_nses = Namespace.builtin_namespaces()
for name, ns_id in builtin_ns.items(): file_ns = Namespace.lookup_name(name, file_nses) self.assertIsInstance(file_ns, Namespace) - image_ns = Namespace.lookup_name(name, image_nses) - self.assertIsInstance(image_ns, Namespace) with self.disable_assert_capture(): self.assertEqual(file_ns.id, ns_id) - self.assertEqual(image_ns.id, ns_id)
class TestNamespaceCollections(TestCase):
pywikibot-commits@lists.wikimedia.org