jenkins-bot merged this change.
[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(-)
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):
To view, visit change 463775. To unsubscribe, or for help writing mail filters, visit settings.