Dachary has uploaded a new change for review.

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

Change subject: bot: implement the Bot base class
......................................................................

bot: implement the Bot base class

The Bot base class automatically fetches entities from attributes such
as

   self.P_protocol
   self.Q_git

If initialized with the test=True argument it works against
test.wikidata.org instead of wikidata.org. If an entity does not exist
in test.wikidata.org a new one is created with the same label. And the
same datatype in the case of a property.

Change-Id: I0a1f0ddf858cbcd319be7fd6d11a012968be623f
Signed-off-by: Loic Dachary <l...@dachary.org>
---
A FLOSSbot/bot.py
A tests/__init__.py
A tests/test_bot.py
A tests/wikidata.py
4 files changed, 225 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/pywikibot/bots/FLOSSbot 
refs/changes/01/311301/1

diff --git a/FLOSSbot/bot.py b/FLOSSbot/bot.py
new file mode 100644
index 0000000..a58920f
--- /dev/null
+++ b/FLOSSbot/bot.py
@@ -0,0 +1,117 @@
+#
+# Copyright (C) 2016 Loic Dachary <l...@dachary.org>
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+import logging
+
+import pywikibot
+
+log = logging.getLogger(__name__)
+
+
+class Bot(object):
+
+    def __init__(self, args):
+        self.args = args
+        self.site = pywikibot.Site(
+            code="wikidata" if not self.args.test else "test",
+            fam="wikidata",
+            user=self.args.user)
+        if self.args.test:
+            self.site.throttle.setDelays(writedelay=0)
+        if self.args.test:
+            self.wikidata_site = pywikibot.Site(code="wikidata",
+                                                fam="wikidata")
+        self.reset_cache()
+
+    def reset_cache(self):
+        self.entities = {
+            'property': {},
+            'item': {},
+        }
+
+    def lookup_entity(self, name, **kwargs):
+        type = kwargs['type']
+        found = self.entities[type].get(name)
+        if found:
+            return found
+        found = self.search_entity(self.site, name, **kwargs)
+        if found:
+            if type == 'property':
+                found = found['id']
+            self.entities[type][name] = found
+        return found
+
+    def search_entity(self, site, name, **kwargs):
+        found = None
+        for p in site.search_entities(name, 'en', **kwargs):
+            if p['label'] == name:
+                if kwargs['type'] == 'property':
+                    found = p
+                else:
+                    found = pywikibot.ItemPage(site, p['id'], 0)
+                break
+        return found
+
+    lookup_item = lookup_entity
+
+    def lookup_property(self, name):
+        return self.lookup_entity(self.site, name, type='property')
+
+    def create_entity(self, type, name):
+        found = self.search_entity(self.wikidata_site, name, type=type)
+        assert found, type + " " + name + " must exist wikidata"
+        entity = {
+            "labels": {
+                "en": {
+                    "language": "en",
+                    "value": name,
+                }
+            },
+        }
+        if type == 'property':
+            id = found['id']
+            found = self.wikidata_site.loadcontent({'ids': id}, 'datatype')
+            assert found, "datatype of " + id + " " + name + " is not found"
+            entity['datatype'] = found[id]['datatype']
+        log.debug("create " + type + " " + str(entity))
+        self.site.editEntity({'new': type}, entity)
+
+    def clear_entity_label(self, id):
+        data = {
+            "labels": {
+                "en": {
+                    "language": "en",
+                    "value": "",
+                }
+            }
+        }
+        log.debug("clear " + id + " label")
+        self.site.editEntity({'id': id}, data)
+        self.reset_cache()
+
+    def __getattribute__(self, name):
+        if name.startswith('P_'):
+            type = 'property'
+        elif name.startswith('Q_'):
+            type = 'item'
+        else:
+            return super(Bot, self).__getattribute__(name)
+        label = " ".join(name.split('_')[1:])
+        found = self.lookup_entity(label, type=type)
+        if not found and self.args.test:
+            self.create_entity(type, label)
+            found = self.lookup_entity(label, type=type)
+        return found
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/__init__.py
diff --git a/tests/test_bot.py b/tests/test_bot.py
new file mode 100644
index 0000000..eead047
--- /dev/null
+++ b/tests/test_bot.py
@@ -0,0 +1,81 @@
+# -*- mode: python; coding: utf-8 -*-
+#
+# Copyright (C) 2016 Loic Dachary <l...@dachary.org>
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+import argparse
+import logging
+
+from FLOSSbot.bot import Bot
+from tests.wikidata import TestWikidata
+
+
+class TestBot(object):
+
+    def setup_class(cls):
+        logging.getLogger('FLOSSbot').setLevel(logging.DEBUG)
+        TestWikidata().login()
+
+    def test_lookup_item(self):
+        bot = Bot(argparse.Namespace(
+            test=True,
+            user='FLOSSbotCI',
+        ))
+        assert 0 == len(bot.entities['item'])
+        git = bot.Q_git
+        assert 1 == len(bot.entities['item'])
+        assert git == bot.Q_git
+        assert bot.Q_Concurrent_Versions_System
+        assert 2 == len(bot.entities['item'])
+
+    def test_create_entity(self):
+        bot = Bot(argparse.Namespace(
+            test=True,
+            user='FLOSSbotCI',
+        ))
+        item = bot.Q_git
+        assert 1 == len(bot.entities['item'])
+        bot.clear_entity_label(item.getID())
+        assert 0 == len(bot.entities['item'])
+        item = bot.Q_git
+        assert 1 == len(bot.entities['item'])
+
+        property2datatype = {
+            'P_source_code_repository': 'url',
+            'P_website_username': 'string',
+            'P_protocol': 'wikibase-item',
+        }
+
+        wikidata_bot = Bot(argparse.Namespace(
+            test=False,
+            user=None,
+        ))
+        for (attr, datatype) in property2datatype.items():
+            bot.reset_cache()
+            property = bot.__getattribute__(attr)
+            assert 1 == len(bot.entities['property'])
+            bot.clear_entity_label(property)
+            assert 0 == len(bot.entities['property'])
+            property = bot.__getattribute__(attr)
+            assert 1 == len(bot.entities['property'])
+
+            new_content = bot.site.loadcontent({'ids': property}, 'datatype')
+            wikidata_property = wikidata_bot.__getattribute__(attr)
+            wikidata_content = wikidata_bot.site.loadcontent(
+                {'ids': wikidata_property}, 'datatype')
+            assert (wikidata_content[wikidata_property]['datatype'] ==
+                    new_content[property]['datatype']), attr
+            assert (datatype ==
+                    wikidata_content[wikidata_property]['datatype']), attr
diff --git a/tests/wikidata.py b/tests/wikidata.py
new file mode 100644
index 0000000..1e46eea
--- /dev/null
+++ b/tests/wikidata.py
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2016 Loic Dachary <l...@dachary.org>
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+import pywikibot
+from pywikibot.data import api
+
+
+class TestWikidata(object):
+
+    def login(self):
+        site = pywikibot.Site("test", "wikidata", "FLOSSbotCI")
+        api.LoginManager(site=site,
+                         user="FLOSSbotCI",
+                         password="yosQuepacAm2").login()

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0a1f0ddf858cbcd319be7fd6d11a012968be623f
Gerrit-PatchSet: 1
Gerrit-Project: pywikibot/bots/FLOSSbot
Gerrit-Branch: master
Gerrit-Owner: Dachary <l...@dachary.org>

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

Reply via email to