John Vandenberg has uploaded a new change for review.
https://gerrit.wikimedia.org/r/186618
Change subject: Fix and test interwiki_graph
......................................................................
Fix and test interwiki_graph
interwiki_graph used compat method Family.get_address, which doesnt
exist in core and caused an exception when creating a graph.
The module also relied on a 'Subject' data structure which was only
defined within interwiki.py. A new simple Subject class has been
added to the interwiki_graph module, and the more advanced class
in interwiki.py is now a subclass.
Added basic dry tests for this module.
Change-Id: If1f41c27a7fec012e9a7c4ce7cb13bb0ecd11c2e
---
M pywikibot/interwiki_graph.py
M scripts/interwiki.py
A tests/interwiki_graph_tests.py
M tests/utils.py
M tox.ini
5 files changed, 167 insertions(+), 17 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/pywikibot/core
refs/changes/18/186618/1
diff --git a/pywikibot/interwiki_graph.py b/pywikibot/interwiki_graph.py
index 00fe657..5e184a4 100644
--- a/pywikibot/interwiki_graph.py
+++ b/pywikibot/interwiki_graph.py
@@ -9,13 +9,17 @@
import threading
-pydotfound = True
try:
import pydot
except ImportError:
- pydotfound = False
+ pydot = False
+
import pywikibot
+
from pywikibot import config2 as config
+
+# deprecated value
+pydotfound = pydot is not False
class GraphImpossible(Exception):
@@ -37,18 +41,43 @@
"""
def __init__(self, graph, originPage):
+ """Constructor."""
threading.Thread.__init__(self)
self.graph = graph
self.originPage = originPage
def run(self):
+ """Write graphs to the data directory."""
for format in config.interwiki_graph_formats:
- filename = 'interwiki-graphs/' + getFilename(self.originPage,
- format)
+ filename = config.datafilepath(
+ 'interwiki-graphs/' + getFilename(self.originPage, format))
if self.graph.write(filename, prog='dot', format=format):
pywikibot.output(u'Graph saved as %s' % filename)
else:
pywikibot.output(u'Graph could not be saved as %s' % filename)
+
+
+class Subject(object):
+
+ """Data about a page with translations on multiple wikis."""
+
+ def __init__(self, originPage=None):
+ """Constructor.
+
+ @param originPage: the page on the 'origin' wiki
+ @type originPage: Page
+ """
+ # Remember the "origin page"
+ self.originPage = originPage
+
+ # foundIn is a dictionary where pages are keys and lists of
+ # pages are values. It stores where we found each page.
+ # As we haven't yet found a page that links to the origin page, we
+ # start with an empty list for it.
+ if originPage:
+ self.foundIn = {self.originPage: []}
+ else:
+ self.foundIn = {}
class GraphDrawer:
@@ -56,21 +85,29 @@
"""Graphviz (dot) code creator."""
def __init__(self, subject):
- """Constructor."""
+ """Constructor.
+
+ @param subject: page data to graph
+ @type subject: Subject
+
+ @raises GraphImpossible: pydot is not installed
+ """
if not pydotfound:
raise GraphImpossible('pydot is not installed.')
self.graph = None
self.subject = subject
def getLabel(self, page):
+ """Get label for page."""
return (u'"\"%s:%s\""' % (page.site.language(),
page.title())).encode('utf-8')
def addNode(self, page):
+ """Add a node for page."""
node = pydot.Node(self.getLabel(page), shape='rectangle')
node.set_URL("\"http://%s%s\""
% (page.site.hostname(),
- page.site.get_address(page.urlname())))
+ page.site.nice_get_address(page.urlname())))
node.set_style('filled')
node.set_fillcolor('white')
node.set_fontsize('11')
@@ -93,6 +130,7 @@
self.graph.add_node(node)
def addDirectedEdge(self, page, refPage):
+ """Add a directed edge from refPage to page."""
# if page was given as a hint, referrers would be [None]
if refPage is not None:
sourceLabel = self.getLabel(refPage)
@@ -130,6 +168,7 @@
self.graph.add_edge(edge)
def saveGraphFile(self):
+ """Write graphs to the data directory."""
thread = GraphSavingThread(self.graph, self.subject.originPage)
thread.start()
diff --git a/scripts/interwiki.py b/scripts/interwiki.py
index 1158110..29899f2 100755
--- a/scripts/interwiki.py
+++ b/scripts/interwiki.py
@@ -771,7 +771,7 @@
yield page
-class Subject(object):
+class Subject(interwiki_graph.Subject):
u"""
Class to follow the progress of a single 'subject'.
@@ -841,8 +841,8 @@
if originPage:
originPage = StoredPage(originPage)
- # Remember the "origin page"
- self.originPage = originPage
+ super(Subject, self).__init__(originPage)
+
self.repoPage = None
# todo is a list of all pages that still need to be analyzed.
# Mark the origin page as todo.
@@ -853,14 +853,6 @@
# done is a list of all pages that have been analyzed and that
# are known to belong to this subject.
self.done = PageTree()
- # foundIn is a dictionary where pages are keys and lists of
- # pages are values. It stores where we found each page.
- # As we haven't yet found a page that links to the origin page, we
- # start with an empty list for it.
- if originPage:
- self.foundIn = {self.originPage: []}
- else:
- self.foundIn = {}
# This is a list of all pages that are currently scheduled for
# download.
self.pending = PageTree()
diff --git a/tests/interwiki_graph_tests.py b/tests/interwiki_graph_tests.py
new file mode 100644
index 0000000..ca096f0
--- /dev/null
+++ b/tests/interwiki_graph_tests.py
@@ -0,0 +1,117 @@
+# -*- coding: utf-8 -*-
+"""Test Interwiki Graph functionality."""
+#
+# (C) Pywikibot team, 2015
+#
+# Distributed under the terms of the MIT license.
+#
+__version__ = '$Id$'
+
+import pywikibot
+
+from pywikibot import interwiki_graph
+
+from tests.aspects import unittest, TestCase
+
+
+class TestWiktionaryGraph(TestCase):
+
+ """Tests for interwiki links to local sites."""
+
+ sites = {
+ 'en': {
+ 'family': 'wiktionary',
+ 'code': 'en',
+ },
+ 'fr': {
+ 'family': 'wiktionary',
+ 'code': 'fr',
+ },
+ 'pl': {
+ 'family': 'wiktionary',
+ 'code': 'pl',
+ },
+ }
+ dry = True
+
+ @classmethod
+ def setUpClass(cls):
+ if not interwiki_graph.pydot:
+ raise unittest.SkipTest('pydot not installed')
+ super(TestWiktionaryGraph, cls).setUpClass()
+
+ def test_simple_graph(self):
+ """Test that GraphDrawer.createGraph does not raise exception."""
+ en = pywikibot.Page(self.get_site('en'), 'origin')
+ fr = pywikibot.Page(self.get_site('fr'), 'origin')
+ pl = pywikibot.Page(self.get_site('pl'), 'origin')
+
+ # Avoid calling server for this test
+ en.exists = lambda: True
+ fr.exists = lambda: True
+ pl.exists = lambda: True
+
+ en.isRedirectPage = en.isDisambig = lambda: False
+ fr.isRedirectPage = fr.isDisambig = lambda: False
+ pl.isRedirectPage = pl.isDisambig = lambda: False
+
+ # Build data and create graph
+ data = interwiki_graph.Subject(en)
+
+ data.foundIn[en] = [fr, pl]
+ data.foundIn[fr] = [en, pl]
+ data.foundIn[pl] = [en, fr]
+
+ drawer = interwiki_graph.GraphDrawer(data)
+
+ drawer.createGraph()
+
+ def test_octagon(self):
+ """Test octagon nodes."""
+ en = pywikibot.Page(self.get_site('en'), 'origin')
+ en2 = pywikibot.Page(self.get_site('en'), 'origin2')
+ fr = pywikibot.Page(self.get_site('fr'), 'origin')
+ pl = pywikibot.Page(self.get_site('pl'), 'origin')
+
+ # Avoid calling server for this test
+ en.exists = lambda: True
+ en2.exists = lambda: True
+ fr.exists = lambda: True
+ pl.exists = lambda: True
+
+ en.isRedirectPage = en.isDisambig = lambda: False
+ en2.isRedirectPage = en2.isDisambig = lambda: False
+ fr.isRedirectPage = fr.isDisambig = lambda: False
+ pl.isRedirectPage = pl.isDisambig = lambda: False
+
+ # Build data and create graph
+ data = interwiki_graph.Subject(en)
+
+ data.foundIn[en] = [fr, pl]
+ data.foundIn[en2] = [fr]
+ data.foundIn[fr] = [en, pl]
+ data.foundIn[pl] = [en, fr]
+
+ drawer = interwiki_graph.GraphDrawer(data)
+
+ drawer.createGraph()
+
+ nodes = drawer.graph.obj_dict['nodes']
+ self.assertEqual(
+ nodes['""pl:origin""'][0]['attributes']['shape'],
+ 'rectangle')
+
+ self.assertEqual(
+ nodes['""fr:origin""'][0]['attributes']['shape'],
+ 'rectangle')
+
+ self.assertEqual(
+ nodes['""en:origin""'][0]['attributes']['shape'],
+ 'octagon')
+
+
+if __name__ == '__main__':
+ try:
+ unittest.main()
+ except SystemExit:
+ pass
diff --git a/tests/utils.py b/tests/utils.py
index 06661e0..041e9cf 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -149,6 +149,7 @@
self._userinfo = pywikibot.tools.EMPTY_DEFAULT
self._siteinfo = DummySiteinfo({})
self._siteinfo._cache['lang'] = (code, True)
+ self._siteinfo._cache['articlepath'] = ('/wiki/$1', True)
self._namespaces = SelfCallDict(Namespace.builtin_namespaces())
@property
diff --git a/tox.ini b/tox.ini
index 5614737..ff4e0b4 100644
--- a/tox.ini
+++ b/tox.ini
@@ -48,6 +48,7 @@
pywikibot/echo.py \
pywikibot/editor.py \
pywikibot/exceptions.py \
+ pywikibot/interwiki_graph.py \
pywikibot/families/ \
pywikibot/fixes.py \
pywikibot/i18n.py \
--
To view, visit https://gerrit.wikimedia.org/r/186618
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: If1f41c27a7fec012e9a7c4ce7cb13bb0ecd11c2e
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: John Vandenberg <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits