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 <[email protected]>
Gerrit-Reviewer: John Vandenberg <[email protected]>
Gerrit-Reviewer: Ladsgroup <[email protected]>
Gerrit-Reviewer: Merlijn van Deen <[email protected]>
Gerrit-Reviewer: Mpaa <[email protected]>
Gerrit-Reviewer: Ricordisamoa <[email protected]>
Gerrit-Reviewer: XZise <[email protected]>
Gerrit-Reviewer: Xqt <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to