Mpaa has uploaded a new change for review.

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

Change subject: proofreadpage.py: add ProofreadPage.index property and other 
methods
......................................................................

proofreadpage.py: add ProofreadPage.index property and other methods

Add:
- ProofreadPage.index property to get Index page containing the page
- IndexPage.page_generator() to load pages related to an Index page in
  specified page range (filters are available for quality level and
  page existance)
- IndexPage.get_number() to get page number of a page

Rename:
- IndexPage.get_page_from_number() to get_page()

Added and cleaned up docstrings.

Added related tests.

Change-Id: I9dab8c2e75dc27fe87500eac3202f14553525a82
---
M pywikibot/proofreadpage.py
M tests/proofreadpage_tests.py
2 files changed, 160 insertions(+), 13 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/pywikibot/core 
refs/changes/89/243489/1

diff --git a/pywikibot/proofreadpage.py b/pywikibot/proofreadpage.py
index edc0060..602c95b 100644
--- a/pywikibot/proofreadpage.py
+++ b/pywikibot/proofreadpage.py
@@ -28,6 +28,8 @@
 
 import pywikibot
 
+from pywikibot.pagegenerators import PreloadingGenerator
+
 
 class FullHeader(object):
 
@@ -70,6 +72,11 @@
     PROOFREAD = 3
     VALIDATED = 4
 
+    # Indicate if page is linked to no/several Index pages.
+    UNLINKED = 0
+    LINKED = 1
+    MULTILINKED = 2
+
     open_tag = '<noinclude>'
     close_tag = '</noinclude>'
     p_open = re.compile(r'<noinclude>')
@@ -89,6 +96,48 @@
         if self.namespace() != site.proofread_page_ns:
             raise ValueError('Page %s must belong to %s namespace'
                              % (self.title(), ns))
+
+    @property
+    def index(self):
+        """Get the Index page which contains ProofreadPage.
+
+        To force reload, delete index and call it again.
+
+        Returns:
+        None:      if ProofreadPage is linked to no or several Index pages.
+        IndexPage: if ProofreadPage is linked to one Index page.
+        """
+        if not hasattr(self, '_index'):
+            index_ns = self.site.proofread_index_ns
+            what_links_here = list(self.getReferences(namespaces=index_ns))
+            if not what_links_here:
+                self._index = (self.UNLINKED, None)
+            elif len(what_links_here) > 1:
+                self._index = (self.MULTILINKED, what_links_here)
+            else:
+                self._index = (self.LINKED, IndexPage(what_links_here[0]))
+
+        status, page = self._index
+        if status == self.UNLINKED:
+            pywikibot.warning('Page %s is not linked to any Index page'
+                              % self)
+        elif status == self.MULTILINKED:
+            pywikibot.warning('Page %s is linked to several Index pages: %s'
+                              % (self, page))
+        else:
+            return page
+
+    @index.setter
+    def index(self, value):
+        if not isinstance(value, IndexPage):
+            raise ValueError('value %s must be a IndexPage object.'
+                             % value)
+        self._index = (self.LINKED, value)
+
+    @index.deleter
+    def index(self):
+        if hasattr(self, "_index"):
+            del self._index
 
     def decompose(fn):
         """Decorator.
@@ -347,6 +396,13 @@
             on de wikisource).
         page label is the label associated with a page in the Index page.
 
+        This class provides methods to get pages contained in Index page,
+        and relative page numbers and labels by means of several helper
+        functions.
+
+        It also providesa generator to pages contained in Index page, with
+        possibility to define range, filter by quality levels and page 
existance.
+
         Raises UnknownExtension if source Site has no ProofreadPage Extension.
         """
         # Check if BeautifulSoup is imported.
@@ -393,6 +449,7 @@
             title = a_tag.get('title')
 
             page = ProofreadPage(self.site, title)
+            page.index = self  # set index property for page
             if page not in self._all_page_links:
                 raise pywikibot.Error('Page %s not recognised.' % page)
 
@@ -434,6 +491,41 @@
             self._get_page_mappings()
         return len(self._page_from_numbers)
 
+    def page_generator(self, start=1, end=None, filter_ql=None,
+                       only_existing=False, preload=True):
+        """Return a page generator which yields pages contained in Index page.
+
+        @param start: first page
+        @type start: int
+        @param end: last page (num_pages if end is greater than num_pages)
+        @type end: int
+        @param filter_ql: filters quality levels (default: all but Without 
Text).
+        @type filter_ql: list of ints  (corresponding to ql constants
+                         defined in ProofreadPage).
+        @param only_exist: yields only existing pages.
+        @type only_exist: bool
+        """
+        # start >= 1
+        start = max(1, start)
+        if end is None:
+            end = self.num_pages
+        else:
+            # start <= end <= num_pages
+            end = min(max(start, end), self.num_pages)
+
+        if filter_ql is None:
+            filter_ql = [1, 2, 3, 4]
+
+        gen = (self.get_page(i) for i in range(start, end + 1))
+        if preload:
+            gen = PreloadingGenerator(gen)
+
+        gen = (p for p in gen if p.ql in filter_ql)
+        if only_existing:
+            gen = (p for p in gen if p.exists())
+
+        return gen
+
     def get_label_from_page(self, page):
         """Return 'page label' for page.
 
@@ -466,7 +558,7 @@
         try:
             return self._labels_from_page_number[page_number]
         except KeyError:
-            raise KeyError('Page number ".../%s" not range.'
+            raise KeyError('Page number ".../%s" not in range.'
                            % page_number)
 
     def _get_from_label(self, mapping_dict, label):
@@ -503,7 +595,7 @@
         """
         return self._get_from_label(self._pages_from_label, label)
 
-    def get_page_from_number(self, page_number):
+    def get_page(self, page_number):
         """Return a page object from page number.
 
         @param page_number: int
@@ -517,3 +609,18 @@
             return self._page_from_numbers[page_number]
         except KeyError:
             raise KeyError('Invalid page number: %s.' % page_number)
+
+    def get_number(self, page):
+        """Return a page number from page object.
+
+        @param page: page object
+        @return: page_number: int
+        @rtype: int
+        """
+        if not self._page_from_numbers:
+            self._get_page_mappings()
+
+        try:
+            return self._numbers_from_page[page]
+        except KeyError:
+            raise KeyError('Invalid page: %s.' % page)
diff --git a/tests/proofreadpage_tests.py b/tests/proofreadpage_tests.py
index 8a1715f..487bf04 100644
--- a/tests/proofreadpage_tests.py
+++ b/tests/proofreadpage_tests.py
@@ -86,6 +86,7 @@
 
     valid = {
         'title': 'Page:Popular Science Monthly Volume 1.djvu/12',
+        'index': 'Index:Popular Science Monthly Volume 1.djvu',
         'ql': 4,
         'user': 'T. Mazzei',
         'header': u"{{rh|2|''THE POPULAR SCIENCE MONTHLY.''}}",
@@ -94,6 +95,10 @@
 
     existing_invalid = {
         'title': 'Main Page',
+    }
+
+    existing_unlinked = {
+        'title': 'Page:Pywikibot unlinked test page',
     }
 
     not_existing_invalid = {
@@ -200,6 +205,18 @@
 
         page_text = page._page_to_json()
         self.assertEqual(json.loads(page_text), json.loads(loaded_text))
+
+    def test_index(self):
+        """Test index property."""
+        # Page with Index.
+        page = ProofreadPage(self.site, self.valid['title'])
+        index_page = IndexPage(self.site, self.valid['index'])
+        self.assertEqual(page.index, index_page)
+
+        # Page without Index.
+        page = ProofreadPage(self.site, self.existing_unlinked['title'])
+        self.assertEqual(page.index, None)
+        self.assertEqual(page._index, (page.UNLINKED, None))
 
 
 @require_modules('bs4')
@@ -382,19 +399,15 @@
         # Error if label does not exists.
         self.assertRaises(KeyError, index_page.get_page_from_label, 'dummy 
label')
 
-        # Test consistency of page <-> numbers mapping on last page_set and
-        # num_set used.
-        for p in page_set:
-            n = index_page._numbers_from_page[p]
-            self.assertEqual(index_page._page_from_numbers[n], p)
+        # Test get_page.
         for n in num_set:
-            p = index_page._page_from_numbers[n]
-            self.assertEqual(index_page._numbers_from_page[p], n)
+            p = index_page.get_page(n)
+            self.assertEqual(index_page.get_number(p), n)
 
-        # Test get_page_from_number.
-        for n in num_set:
-            p = index_page.get_page_from_number(n)
-            self.assertEqual(index_page._numbers_from_page[p], n)
+        # Test get_number.
+        for p in page_set:
+            n = index_page.get_number(p)
+            self.assertEqual(index_page.get_page(n), p)
 
     def test_page_number_mapping(self, key):
         """Test consistency of page <-> mapping."""
@@ -415,6 +428,33 @@
         # Error if page does not exists.
         self.assertRaises(KeyError, index_page.get_label_from_page, None)
 
+    def test_index_property(self, key):
+        """Test index property."""
+        data = self.sites[key]
+        index_page = IndexPage(self.site, self.sites[key]['index'])
+
+        # Get page_set to test (reuse pages used for label tests
+        # (label is not used here).
+        for label, page_set in data['get_page']:
+            for page in page_set:
+                self.assertEqual(page.index, index_page)
+                # test deleter
+                del page.index
+                self.assertFalse(hasattr(page, '_index'))
+                # test setter
+                page.index = index_page
+                self.assertEqual(page.index, index_page)
+
+    def test_page_generator(self, key):
+        """Test Index page generator."""
+        index_page = IndexPage(self.site, self.sites[key]['index'])
+
+        gen = index_page.page_generator(-1, -1, filter_ql=range(5))
+        self.assertEqual(len(list(gen)), 1)
+
+        gen = index_page.page_generator(end=10, filter_ql=range(5))
+        self.assertEqual(len(list(gen)), 10)
+
 
 if __name__ == '__main__':
     try:

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I9dab8c2e75dc27fe87500eac3202f14553525a82
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: Mpaa <[email protected]>

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

Reply via email to