jenkins-bot has submitted this change and it was merged.
Change subject: Python 2.6 collections backports & failover
......................................................................
Python 2.6 collections backports & failover
collections.Counter and .OrderedDict are a Python 2.7+ feature.
On Python 2.6, use backport package `future` by default, but also
use ordereddict and Counter packages if they are installed.
When a suitable implementation doesn't exist, provide a fake
class which raises an exception on use, so that it isn't
failing on import.
Bug: T72707
Change-Id: I265ee4726d124b8e5dfa8ec2e2f9314b2c2132e7
---
M pywikibot/page.py
M pywikibot/textlib.py
M pywikibot/tools.py
M setup.py
M tests/__init__.py
M tests/textlib_tests.py
M tests/wikibase_tests.py
7 files changed, 69 insertions(+), 59 deletions(-)
Approvals:
John Vandenberg: Looks good to me, but someone else must approve
Mpaa: Looks good to me, approved
jenkins-bot: Verified
diff --git a/pywikibot/page.py b/pywikibot/page.py
index 1c318df..80b6ec7 100644
--- a/pywikibot/page.py
+++ b/pywikibot/page.py
@@ -17,19 +17,14 @@
__version__ = '$Id$'
#
-import collections
import hashlib
import logging
import re
import sys
import unicodedata
+from collections import defaultdict, namedtuple
from warnings import warn
-
-try:
- from collections import OrderedDict
-except ImportError:
- from ordereddict import OrderedDict
if sys.version_info[0] > 2:
unicode = basestring = str
@@ -44,6 +39,7 @@
from urllib import urlopen
import pywikibot
+
from pywikibot import config
from pywikibot.family import Family
from pywikibot.site import Namespace
@@ -54,6 +50,7 @@
from pywikibot.tools import (
ComparableMixin, deprecated, deprecate_arg, deprecated_args,
remove_last_args, _NotImplementedWarning,
+ OrderedDict, Counter,
)
from pywikibot import textlib
@@ -3096,8 +3093,8 @@
empty = len(diffto['aliases'][lang]) - len(strings)
if empty > 0:
strings += [''] * empty
- elif collections.Counter(val['value'] for val in
diffto['aliases'][lang]
- ) == collections.Counter(strings):
+ elif Counter(val['value'] for val
+ in diffto['aliases'][lang]) == Counter(strings):
del aliases[lang]
if lang in aliases:
aliases[lang] = [{'language': lang, 'value': i} for i in
strings]
@@ -4005,7 +4002,7 @@
@type claims: list of pywikibot.Claim
"""
data = self.repo.editSource(self, claims, new=True, **kwargs)
- source = collections.defaultdict(list)
+ source = defaultdict(list)
for claim in claims:
claim.hash = data['reference']['hash']
self.on_item.lastrevid = data['pageinfo']['lastrevid']
@@ -4030,7 +4027,7 @@
"""
self.repo.removeSources(self, sources, **kwargs)
for source in sources:
- source_dict = collections.defaultdict(list)
+ source_dict = defaultdict(list)
source_dict[source.getID()].append(source)
self.sources.remove(source_dict)
@@ -4151,18 +4148,16 @@
"""A structure holding information about a single revision of a
Page."""
- HistEntry = collections.namedtuple('HistEntry',
- ['revid',
- 'timestamp',
- 'user',
- 'comment'])
+ HistEntry = namedtuple('HistEntry', ['revid',
+ 'timestamp',
+ 'user',
+ 'comment'])
- FullHistEntry = collections.namedtuple('FullHistEntry',
- ['revid',
- 'timestamp',
- 'user',
- 'text',
- 'rollbacktoken'])
+ FullHistEntry = namedtuple('FullHistEntry', ['revid',
+ 'timestamp',
+ 'user',
+ 'text',
+ 'rollbacktoken'])
def __init__(self, revid, timestamp, user, anon=False, comment=u"",
text=None, minor=False, rollbacktoken=None):
diff --git a/pywikibot/textlib.py b/pywikibot/textlib.py
index 530dc70..96f1ff6 100644
--- a/pywikibot/textlib.py
+++ b/pywikibot/textlib.py
@@ -18,11 +18,6 @@
import re
import sys
-try:
- from collections import OrderedDict
-except ImportError:
- from ordereddict import OrderedDict
-
if sys.version_info[0] > 2:
from html.parser import HTMLParser
basestring = (str,)
@@ -30,10 +25,11 @@
else:
from HTMLParser import HTMLParser
-from pywikibot import config2 as config
import pywikibot
-from pywikibot.family import Family
+from pywikibot import config2 as config
+from pywikibot.family import Family
+from pywikibot.tools import OrderedDict
TEMP_REGEX = re.compile(
'{{(?:msg:)?(?P<name>[^{\|]+?)(?:\|(?P<params>[^{]+?(?:{[^{]+?}[^{]*?)?))?}}')
diff --git a/pywikibot/tools.py b/pywikibot/tools.py
index 6037195..61577d2 100644
--- a/pywikibot/tools.py
+++ b/pywikibot/tools.py
@@ -16,9 +16,8 @@
import time
import types
-from warnings import warn
-
from distutils.version import Version
+from warnings import warn
if sys.version_info[0] > 2:
import queue as Queue
@@ -42,6 +41,43 @@
"""Feature that is no longer implemented."""
pass
+
+
+class NotImplementedClass(object):
+
+ """No implementation is available."""
+
+ def __init__(self, *args, **kwargs):
+ """Constructor."""
+ raise NotImplementedError(
+ '%s: %s' % (self.__class__.__name__, self.__doc__))
+
+
+if sys.version_info < (2, 7):
+ try:
+ from future.backports.misc import Counter, OrderedDict
+ except ImportError:
+ try:
+ from ordereddict import OrderedDict
+ except ImportError:
+ class OrderedDict(NotImplementedClass):
+
+ """OrderedDict not found."""
+
+ pass
+
+ try:
+ from counter import Counter
+ except ImportError:
+ class Counter(NotImplementedClass):
+
+ """Counter not found."""
+
+ pass
+
+else:
+ from collections import Counter # noqa ; unused
+ from collections import OrderedDict
def empty_iterator():
@@ -793,7 +829,7 @@
if wrapper.__signature__:
# Build a new signature with deprecated args added.
- params = collections.OrderedDict()
+ params = OrderedDict()
for param in wrapper.__signature__.parameters.values():
params[param.name] = param.replace()
for old_arg, new_arg in arg_pairs.items():
diff --git a/setup.py b/setup.py
index 377913b..7ba08ae 100644
--- a/setup.py
+++ b/setup.py
@@ -66,7 +66,7 @@
sys.modules['unittest'] = unittest2
script_deps['replicate_wiki.py'] = ['argparse']
- dependencies.append('ordereddict')
+ dependencies.append('future') # provides collections backports
if sys.version_info[0] == 3:
if sys.version_info[1] < 3:
diff --git a/tests/__init__.py b/tests/__init__.py
index dbc93d9..16c7dc5 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -11,32 +11,19 @@
import sys
import warnings
-__all__ = ('httplib2', 'OrderedDict', '_cache_dir',
'TestRequest',
+__all__ = ('httplib2', '_cache_dir', 'TestRequest',
'patch_request', 'unpatch_request')
# Verify that the unit tests have a base working environment:
# - httplib2 is mandatory
-# - ordereddict is only needed as a fallback for python 2.6
+# - ordereddict is needed as a fallback for python 2.6,
+# however if unavailable this will fail on use; see pywikibot/tools.py
# - mwparserfromhell is optional, so is only imported in textlib_tests
try:
import httplib2 # noqa
except ImportError as e:
print("ImportError: %s" % e)
sys.exit(1)
-
-try:
- from collections import OrderedDict # noqa
-except ImportError:
- try:
- from ordereddict import OrderedDict # noqa
- except ImportError as e:
- print("ImportError: %s" % e)
- if sys.version_info[0] == 2 and sys.version_info[1] == 6:
- print(
- "pywikibot depends on module ordereddict in Python 2.6.\n"
- "Run 'pip install ordereddict' to run these tests under
"
- "Python 2.6")
- sys.exit(1)
if sys.version_info < (2, 7):
# Unittest2 is a backport of python 2.7s unittest module to python 2.6
diff --git a/tests/textlib_tests.py b/tests/textlib_tests.py
index 2ade780..903c34f 100644
--- a/tests/textlib_tests.py
+++ b/tests/textlib_tests.py
@@ -12,9 +12,10 @@
import pywikibot
import pywikibot.textlib as textlib
-from pywikibot import config
-from tests import OrderedDict
+from pywikibot import config
+from pywikibot.tools import OrderedDict
+
from tests.aspects import unittest, TestCase, DefaultDrySiteTestCase
files = {}
diff --git a/tests/wikibase_tests.py b/tests/wikibase_tests.py
index c07a03f..b0b7cfa 100644
--- a/tests/wikibase_tests.py
+++ b/tests/wikibase_tests.py
@@ -8,15 +8,16 @@
__version__ = '$Id$'
#
+import copy
+import json
import os
-import sys
+
import pywikibot
+
from pywikibot import pagegenerators
from pywikibot.tools import SelfCallDict
from pywikibot.page import WikibasePage
from pywikibot.site import Namespace
-import json
-import copy
from tests.aspects import unittest, WikidataTestCase, TestCase
@@ -889,12 +890,6 @@
"""Test cases to test toJSON() functions."""
dry = True
-
- @classmethod
- def setUpClass(cls):
- if not sys.version_info >= (2, 7):
- raise unittest.SkipTest("Fails on Python 2.6")
- super(TestJSON, cls).setUpClass()
def setUp(self):
super(TestJSON, self).setUp()
--
To view, visit
https://gerrit.wikimedia.org/r/147665
To unsubscribe, visit
https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I265ee4726d124b8e5dfa8ec2e2f9314b2c2132e7
Gerrit-PatchSet: 11
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: Mpaa <mpaa.wiki(a)gmail.com>
Gerrit-Reviewer: Ricordisamoa <ricordisamoa(a)openmailbox.org>
Gerrit-Reviewer: XZise <CommodoreFabianus(a)gmx.de>
Gerrit-Reviewer: Xqt <info(a)gno.de>
Gerrit-Reviewer: jenkins-bot <>