John Vandenberg has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/151617

Change subject: Add Namespace class
......................................................................

Add Namespace class

Replaces the current implicit data structure of
site._namespaces with a class with variables with
names that explain their contents.

Change-Id: I0cce21e6161031861c0056dc5498f47bc26e1cc8
---
M pywikibot/site.py
M tests/dry_api_tests.py
M tests/dry_site_tests.py
M tests/site_tests.py
4 files changed, 95 insertions(+), 48 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/pywikibot/core 
refs/changes/17/151617/1

diff --git a/pywikibot/site.py b/pywikibot/site.py
index c26e8cd..3d9cf70 100644
--- a/pywikibot/site.py
+++ b/pywikibot/site.py
@@ -20,6 +20,7 @@
 import re
 import sys
 from distutils.version import LooseVersion as LV
+from collections import Iterable
 import threading
 import time
 import urllib
@@ -121,6 +122,51 @@
     return _families[fam]
 
 
+class Namespace(Iterable):
+
+    """ Namespace site data object.
+
+    This is backwards compatible with the structure of entries
+    in site._namespaces which were a list of
+    [customised namespace?,
+     canonical namespace name,
+     namespace alias*]
+    """
+
+    def __init__(self, canonical_name, custom_name=None, aliases=None):
+        """Constructor."""
+        self.canonical_name = canonical_name
+        self.custom_name = custom_name
+        if aliases is None:
+            self.aliases = list()
+        else:
+            self.aliases = aliases
+
+    def __len__(self):
+        """Obtain length of the iterable."""
+        if self.custom_name:
+            return len(self.aliases) + 2
+        else:
+            return len(self.aliases) + 1
+
+    def __iter__(self):
+        """Obtain length of the iterable."""
+        return iter([self.canonical_name, self.custom_name] + self.aliases)
+
+    def __getitem__(self, index):
+        """Obtain an item from the iterable."""
+        if self.custom_name:
+            if index == 0:
+                return self.custom_name
+            else:
+                index -= 1
+
+        if index == 0:
+            return self.canonical_name
+        else:
+            return self.aliases[index - 2]
+
+
 class BaseSite(object):
 
     """Site methods that are independent of the communication interface."""
@@ -144,6 +190,35 @@
             self.__family = Family(fam, fatal=False)
         else:
             self.__family = fam
+
+        self._namespaces = {
+            # These are the MediaWiki built-in names, which always work.
+            # Localized names are loaded later upon accessing the wiki.
+            # Namespace prefixes are always case-insensitive, but the
+            # canonical forms are capitalized
+            -2: [u"Media"],
+            -1: [u"Special"],
+            0: [u""],
+            1: [u"Talk"],
+            2: [u"User"],
+            3: [u"User talk"],
+            4: [u"Project"],
+            5: [u"Project talk"],
+            6: [u"Image"],
+            7: [u"Image talk"],
+            8: [u"MediaWiki"],
+            9: [u"MediaWiki talk"],
+            10: [u"Template"],
+            11: [u"Template talk"],
+            12: [u"Help"],
+            13: [u"Help talk"],
+            14: [u"Category"],
+            15: [u"Category talk"],
+        }
+        # .version() depends on __family
+        if LV(self.version()) >= LV("1.14"):
+            self._namespaces[6] = [u"File"]
+            self._namespaces[7] = [u"File talk"]
 
         self.obsolete = False
         # if we got an outdated language code, use the new one instead.
@@ -633,33 +708,6 @@
     def __init__(self, code, fam=None, user=None, sysop=None):
         """ Constructor. """
         BaseSite.__init__(self, code, fam, user, sysop)
-        self._namespaces = {
-            # These are the MediaWiki built-in names, which always work.
-            # Localized names are loaded later upon accessing the wiki.
-            # Namespace prefixes are always case-insensitive, but the
-            # canonical forms are capitalized
-            -2: [u"Media"],
-            -1: [u"Special"],
-            0: [u""],
-            1: [u"Talk"],
-            2: [u"User"],
-            3: [u"User talk"],
-            4: [u"Project"],
-            5: [u"Project talk"],
-            6: [u"Image"],
-            7: [u"Image talk"],
-            8: [u"MediaWiki"],
-            9: [u"MediaWiki talk"],
-            10: [u"Template"],
-            11: [u"Template talk"],
-            12: [u"Help"],
-            13: [u"Help talk"],
-            14: [u"Category"],
-            15: [u"Category talk"],
-        }
-        if LV(self.version()) >= LV("1.14"):
-            self._namespaces[6] = [u"File"]
-            self._namespaces[7] = [u"File talk"]
         self._msgcache = {}
         self._loginstatus = LoginStatus.NOT_ATTEMPTED
         return
@@ -1214,31 +1262,25 @@
         self._siteinfo = sidata['general']
 
         nsdata = sidata['namespaces']
+        aliasdata = None
+        if 'namespacealiases' in sidata:
+            aliasdata = sidata['namespacealiases']
+
         for nskey in nsdata:
             ns = int(nskey)
-            # this is the preferred form so it goes at front of list
-            self._namespaces.setdefault(ns, []).insert(0, nsdata[nskey]["*"])
-
-            if LV(self.version()) >= LV("1.14"):
-                # nsdata["0"] has no canonical key.
-                # canonical ns -2 to 15 are hard coded in self._namespaces
-                # do not get them from API result to avoid canonical duplicates
-                if -2 <= ns <= 15:
-                    continue
-                if 'canonical' not in nsdata[nskey]:
-                    pywikibot.warning(
-                        u'namespace %s without a canonical name. 
Misconfigured?'
-                        % self._namespaces[ns][0])
-                    continue
-                self._namespaces.setdefault(ns, 
[]).append(nsdata[nskey]["canonical"])
+            if ns == 0:
+                canonical = ''
+            else:
+                assert('canonical' in nsdata[nskey])
+                canonical = nsdata[nskey]['canonical']
+            namespace = Namespace(canonical, nsdata[nskey]["*"])
+            self._namespaces[ns] = namespace
 
         if 'namespacealiases' in sidata:
             aliasdata = sidata['namespacealiases']
             for item in aliasdata:
-                if item["*"] in self._namespaces[int(item['id'])]:
-                    continue
-                # this is a less preferred form so it goes at the end
-                self._namespaces[int(item['id'])].append(item["*"])
+                id = int(item['id'])
+                self._namespaces[id].aliases.append(item["*"])
 
         if 'extensions' in sidata:
             self._extensions = sidata['extensions']
diff --git a/tests/dry_api_tests.py b/tests/dry_api_tests.py
index 1714b59..af05a86 100644
--- a/tests/dry_api_tests.py
+++ b/tests/dry_api_tests.py
@@ -68,6 +68,9 @@
                 self._user = 'anon'
                 pywikibot.site.BaseSite.__init__(self, 'mock', MockFamily())
 
+            def version(self):
+                return '1.13'  # pre 1.14
+
             def languages(self):
                 return ['mock']
 
diff --git a/tests/dry_site_tests.py b/tests/dry_site_tests.py
index 573c89e..c67e87f 100644
--- a/tests/dry_site_tests.py
+++ b/tests/dry_site_tests.py
@@ -53,6 +53,7 @@
         self._logged_in_as = None
         self.obsolete = False
         super(TestMustBe, self).setUp()
+        self.version = lambda: '1.13'  # pre 1.14
 
     def login(self, sysop):
         # mock call
diff --git a/tests/site_tests.py b/tests/site_tests.py
index 4550618..9a90848 100644
--- a/tests/site_tests.py
+++ b/tests/site_tests.py
@@ -11,6 +11,7 @@
 
 
 from distutils.version import LooseVersion as LV
+from collections import Iterable
 import pywikibot
 from tests.utils import PywikibotTestCase, unittest
 
@@ -115,14 +116,14 @@
         self.assertType(mysite.ns_normalize("project"), basestring)
         self.assertTrue(all(isinstance(key, int)
                             for key in ns))
-        self.assertTrue(all(isinstance(val, list)
+        self.assertTrue(all(isinstance(val, Iterable)
                             for val in ns.values()))
         self.assertTrue(all(isinstance(name, basestring)
                             for val in ns.values()
                             for name in val))
         self.assertTrue(all(isinstance(mysite.namespace(key), basestring)
                             for key in ns))
-        self.assertTrue(all(isinstance(mysite.namespace(key, True), list)
+        self.assertTrue(all(isinstance(mysite.namespace(key, True), Iterable)
                             for key in ns))
         self.assertTrue(all(isinstance(item, basestring)
                             for key in ns

-- 
To view, visit https://gerrit.wikimedia.org/r/151617
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0cce21e6161031861c0056dc5498f47bc26e1cc8
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <jay...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to