http://www.mediawiki.org/wiki/Special:Code/pywikipedia/11182

Revision: 11182
Author:   legoktm
Date:     2013-03-06 13:30:42 +0000 (Wed, 06 Mar 2013)
Log Message:
-----------
Add initial implementation of WikibasePage (more detailed post to ML will folow)

*This creates a base WikibasePage, ItemPage, PropertyPage, QueryPage, and Claim 
classes.
*Currently only read access is availible, write access will follow.
*Existing methods using DataSite class are not being removed, but
will be phased out in the future.

Modified Paths:
--------------
    branches/rewrite/pywikibot/__init__.py
    branches/rewrite/pywikibot/page.py

Modified: branches/rewrite/pywikibot/__init__.py
===================================================================
--- branches/rewrite/pywikibot/__init__.py      2013-03-06 08:13:25 UTC (rev 
11181)
+++ branches/rewrite/pywikibot/__init__.py      2013-03-06 13:30:42 UTC (rev 
11182)
@@ -178,7 +178,7 @@
 getSite = Site # alias for backwards-compability
 
 
-from page import Page, ImagePage, Category, Link, User
+from page import Page, ImagePage, Category, Link, User, ItemPage, 
PropertyPage, Claim
 from page import html2unicode, url2unicode
 
 

Modified: branches/rewrite/pywikibot/page.py
===================================================================
--- branches/rewrite/pywikibot/page.py  2013-03-06 08:13:25 UTC (rev 11181)
+++ branches/rewrite/pywikibot/page.py  2013-03-06 13:30:42 UTC (rev 11182)
@@ -2184,6 +2184,271 @@
             yield ImagePage(self.site, item.title().title()), \
                   unicode(item.timestamp()), item.comment(), item.pageid() > 0
 
+class WikibasePage(Page):
+    """
+    The base page for the Wikibase extension.
+    There really should be no need to call this directly
+    """
+    def __init__(self, site, title=u""):
+        Page.__init__(self, site, title)
+        if isinstance(self.site, pywikibot.site.DataSite):
+            self.repo = self.site
+        else:
+            self.repo = self.site.data_repository()
+
+    def __defined_by(self):
+        """
+        returns the parameters needed by the API
+        to identify an item.
+        Once an item's "p/q##" is looked up, that
+        will be used for all future requests.
+        """
+        params = {}
+        #id overrides all
+        if hasattr(self, 'id'):
+            params['ids'] = self.id
+            return params
+
+        #the rest only applies to ItemPages, but is still needed here.
+
+        if isinstance(self.site, pywikibot.site.DataSite):
+            params['ids'] = self.title(withNamespace=False)
+        elif isinstance(self.site, pywikibot.site.BaseSite):
+            params['sites'] = self.site.dbName()
+            params['titles'] = self.title()
+        else:
+            raise pywikibot.exceptions.BadTitle
+        return params
+
+    def get(self, force=False, *args):
+        """
+        Fetches all page data, and caches it
+        force will override caching
+        args can be used to specify custom props.
+        """
+        if force or not hasattr(self, '_content'):
+            params = dict(**self.__defined_by())
+            params['action'] = 'wbgetentities'
+            if args:
+                params['props'] = '|'.join(args)
+                #print params
+            req = pywikibot.data.api.Request(site=self.repo, **params)
+            data = req.submit()
+            if not 'success' in data:
+                raise pywikibot.data.api.APIError, data['errors']
+            self.id = data['entities'].keys()[0]
+            self._content = data['entities'][self.id]
+            #aliases
+        self.aliases = {}
+        if 'aliases' in self._content:
+            for lang in self._content['aliases']:
+                self.aliases[lang] = list()
+                for value in self._content['aliases'][lang]:
+                    self.aliases[lang].append(value['value'])
+
+        #labels
+        self.labels = {}
+        if 'labels' in self._content:
+            for lang in self._content['labels']:
+                self.labels[lang] = self._content['labels'][lang]['value']
+
+        #descriptions
+        self.descriptions = {}
+        if 'descriptions' in self._content:
+            for lang in self._content['descriptions']:
+                self.descriptions[lang] = 
self._content['descriptions'][lang]['value']
+
+        return {'aliases':self.aliases,
+                'labels':self.labels,
+                'descriptions':self.descriptions,
+                }
+
+
+
+    def save(self, summary, **kwargs):
+        """
+        Save whatever we added/removed/etc.
+        """
+        raise NotImplementedError
+
+
+class ItemPage(WikibasePage):
+    def __init__(self, site, title=None):
+        """
+        defined by qid XOR site AND title
+        options:
+        site=pywikibot.DataSite & title=Q42
+        site=pywikibot.Site & title=Main Page
+        """
+        WikibasePage.__init__(self, site, title)
+
+    @staticmethod
+    def fromPage(page):
+        """
+        Get the ItemPage based on a Page that links to it
+        """
+        return ItemPage(page.site, page.title())
+
+    def __make_site(self, dbname):
+        """
+        Converts a Site.dbName() into a Site object.
+        Rather hackish method that only works for WMF sites
+        """
+        lang = dbname.replace('wiki','')
+        lang = lang.replace('_','-')
+        return pywikibot.Site(lang, 'wikipedia')
+
+    def get(self, force=False, *args):
+        """
+        Fetches all page data, and caches it
+        force will override caching
+        args are the values of props
+        """
+        if force or not hasattr(self, '_content'):
+            WikibasePage.get(self, force=force, *args)
+
+        #claims
+        self.claims = {}
+        if 'claims' in self._content:
+            for pid in self._content['claims']:
+                self.claims[pid] = list()
+                for claim in self._content['claims'][pid]:
+                    self.claims[pid].append(Claim.fromJSON(self.repo, claim))
+
+        #sitelinks
+        self.sitelinks = {}
+        if 'sitelinks' in self._content:
+            for dbname in self._content['sitelinks']:
+                #Due to issues with locked/obsolete sites
+                #this part is commented out
+                #site = self.__make_site(dbname)
+                #self.sitelinks[site] = pywikibot.Page(site, 
self._content['sitelinks'][dbname]['title'])
+                self.sitelinks[dbname] = 
self._content['sitelinks'][dbname]['title']
+
+        return {'aliases': self.aliases,
+                'labels': self.labels,
+                'descriptions': self.descriptions,
+                'sitelinks': self.sitelinks,
+                'claims': self.claims
+        }
+
+    def get_sitelink(self, site, force=False):
+        """
+        Returns a page object for the specific site
+        site is a pywikibot.Site
+        force will override caching
+        If the item doesn't have that language, raise NoPage
+        """
+        if force or not hasattr(self, '_content'):
+            self.get(force=force)
+        dbname = site.dbName()
+        if not dbname in self.sitelinks:
+            raise pywikibot.NoPage
+        else:
+            return self.sitelinks[dbname]
+
+
+class PropertyPage(WikibasePage):
+    """
+    Any page in the property namespace
+    Should be created as:
+        PropertyPage(DataSite, 'Property:P21')
+    """
+    def __init__(self, source, title=u""):
+        WikibasePage.__init__(self, source, title)
+        self.id = self.title(withNamespace=False).lower()
+        if not self.id.startswith(u'p'):
+            raise ValueError(u"'%s' is not a property page!" % self.title())
+
+    def get_type(self):
+        """
+        Returns the type that this item uses
+        Examples: item, commons media file, StringValue, NumericalValue
+        """
+        raise NotImplementedError
+
+class QueryPage(WikibasePage):
+    """
+    For future usage, not implemented yet
+    """
+    def __init__(self, site, title):
+        WikibasePage.__init__(self, site, title)
+        raise NotImplementedError
+
+
+class Claim(PropertyPage):
+    """
+    Claims are standard claims as well as references.
+    """
+    def __init__(self, site, pid, snak=None, isReference=False):
+        """
+        Defined by the "snak" value, supplemented by site + pid
+        """
+        PropertyPage.__init__(self, site, 'Property:'+pid)
+        self.snak = snak
+        self.isReference = isReference
+        self.sources = []
+        self.target = None
+
+    @staticmethod
+    def fromJSON(site, data):
+        """
+        Creates the claim object from JSON returned
+        in the API call.
+        """
+        claim = Claim(site, data['mainsnak']['property'])
+        if 'id' in data:
+            claim.snak = data['id']
+        else:
+            claim.isReference = True
+        if data['mainsnak']['datavalue']['type'] == 'wikibase-entityid':
+            claim.target = ItemPage(site, 'Q' +
+                                          
str(data['mainsnak']['datavalue']['value']['numeric-id']))
+        else:
+            claim.target = data['mainsnak']['datavalue']['value']
+        if 'references' in data:
+            for source in data['references']:
+                claim.sources.append(Claim.referenceFromJSON(site, 
source['snaks'].values()[0][0]))
+        return claim
+
+    @staticmethod
+    def referenceFromJSON(site, data):
+        """
+        This is a simple hack since reference objects
+        aren't wrapped in a mainsnak object.
+        """
+        wrap = {'mainsnak': data}
+        return Claim.fromJSON(site, wrap)
+
+    def set_target(self, value):
+        """
+        Sets the target to the passed value.
+        There should be checks to ensure type compliance
+        """
+        self.target = value
+
+    def get_target(self):
+        """
+        Returns object that the property is associated with.
+        None is returned if no target is set
+        """
+        return self.target
+
+    def get_sources(self):
+        """
+        Returns a list of Claims
+        """
+        return self.sources
+
+    def add_source(self, source):
+        """
+        source is a Claim.
+        adds it as a reference.
+        """
+        raise NotImplementedError
+
+
+
 class Revision(object):
     """A structure holding information about a single revision of a Page."""
     def __init__(self, revid, timestamp, user, anon=False, comment=u"",


_______________________________________________
Pywikipedia-svn mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/pywikipedia-svn

Reply via email to