Site: Store namespace information in self._namespaces, a dict where key is a namespace ID and value is a list of
matching names and aliases; added _get_namespaces_from_api(), namespaces(), namespace_id_to_name() and
namespace_name_to_id(); get_page() and get_category() are smarter;
Constants: new module, with 18 variables starting with "NS_" that hold IDs of common namespaces, e.g NS_USER = 2,
NS_PROJECT = 4;
Exceptions: added NamespaceNotFoundError, raised by Site when bad input is given to namespace_id_to_name() or
namespace_name_to_id();
User: self.name -> self._name; new name() method returns name from API; dropping "get" from methods that return
just a variable;
Category: get_members() -> members().
tags/v0.1^2
| @@ -10,6 +10,7 @@ written by Mr.Z-man, other than a similar purpose. We share no code. | |||
| Import the toolset with `from wiki import tools`. | |||
| """ | |||
| from wiki.tools.constants import * | |||
| from wiki.tools.exceptions import * | |||
| from wiki.tools.functions import * | |||
| @@ -7,7 +7,7 @@ class Category(Page): | |||
| EarwigBot's Wiki Toolset: Category Class | |||
| """ | |||
| def get_members(self, limit=50): | |||
| def members(self, limit=50): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| @@ -0,0 +1,27 @@ | |||
| # -*- coding: utf-8 -*- | |||
| """ | |||
| EarwigBot's Wiki Toolset: Constants | |||
| This module defines some useful constants. | |||
| """ | |||
| # Default namespace IDs | |||
| NS_MAIN = 0 | |||
| NS_TALK = 1 | |||
| NS_USER = 2 | |||
| NS_USER_TALK = 3 | |||
| NS_PROJECT = 4 | |||
| NS_PROJECT_TALK = 5 | |||
| NS_FILE = 6 | |||
| NS_FILE_TALK = 7 | |||
| NS_MEDIAWIKI = 8 | |||
| NS_MEDIAWIKI_TALK = 9 | |||
| NS_TEMPLATE = 10 | |||
| NS_TEMPLATE_TALK = 11 | |||
| NS_HELP = 12 | |||
| NS_HELP_TALK = 13 | |||
| NS_CATEGORY = 14 | |||
| NS_CATEGORY_TALK = 15 | |||
| NS_SPECIAL = -1 | |||
| NS_MEDIA = -2 | |||
| @@ -13,5 +13,8 @@ class SiteNotFoundError(WikiToolsetError): | |||
| """A site matching the args given to get_site() could not be found in the | |||
| config file.""" | |||
| class NamespaceNotFoundError(WikiToolsetError): | |||
| """A requested namespace name or namespace ID does not exist.""" | |||
| class UserNotFoundError(WikiToolsetError): | |||
| """Attempting to get information about a user that does not exist.""" | |||
| @@ -23,7 +23,7 @@ class Page(object): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| if content is None or force_reload: | |||
| if self._content is None or force_reload: | |||
| params = {"action": "query", "prop": "revisions", | |||
| "rvprop": "content", "rvlimit": 1, "titles": self.title} | |||
| result = self.site.api_query(params) | |||
| @@ -5,6 +5,8 @@ from urllib import urlencode | |||
| from urllib2 import urlopen | |||
| from wiki.tools.category import Category | |||
| from wiki.tools.constants import * | |||
| from wiki.tools.exceptions import NamespaceNotFoundError | |||
| from wiki.tools.page import Page | |||
| from wiki.tools.user import User | |||
| @@ -22,6 +24,37 @@ class Site(object): | |||
| self.lang = lang | |||
| self._api = api | |||
| self._sql = sql | |||
| self._namespaces = None | |||
| def _get_namespaces_from_api(self): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| params = {"action": "query", "meta": "siteinfo", | |||
| "siprop": "namespaces|namespacealiases"} | |||
| result = self.api_query(params) | |||
| if self._namespaces is None: | |||
| self._namespaces = {} | |||
| for namespace in result["query"]["namespaces"].values(): | |||
| ns_id = namespace["id"] | |||
| name = namespace["*"] | |||
| try: | |||
| canonical = namespace["canonical"] | |||
| except KeyError: | |||
| self._namespaces[ns_id] = [name] | |||
| else: | |||
| if name != canonical: | |||
| self._namespaces[ns_id] = [name, canonical] | |||
| else: | |||
| self._namespaces[ns_id] = [name] | |||
| for namespace in result["query"]["namespacealiases"]: | |||
| ns_id = namespace["id"] | |||
| alias = namespace["*"] | |||
| self._namespaces[ns_id].append(alias) | |||
| def api_query(self, params): | |||
| """ | |||
| @@ -32,19 +65,65 @@ class Site(object): | |||
| result = urlopen(self._api, data).read() | |||
| return loads(result) | |||
| def namespaces(self): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| if self._namespaces is None: | |||
| self._get_namespaces_from_api() | |||
| return self._namespaces | |||
| def namespace_id_to_name(self, ns_id, all=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| if self._namespaces is None: | |||
| self._get_namespaces_from_api() | |||
| try: | |||
| if all: | |||
| return self._namespaces[ns_id] | |||
| else: | |||
| return self._namespaces[ns_id][0] | |||
| except KeyError: | |||
| e = "There is no namespace with id {0}.".format(ns_id) | |||
| raise NamespaceNotFoundError(e) | |||
| def namespace_name_to_id(self, name): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| if self._namespaces is None: | |||
| self._get_namespaces_from_api() | |||
| lname = name.lower() | |||
| for ns_id, names in self._namespaces.items(): | |||
| lnames = [n.lower() for n in names] # be case-insensitive | |||
| if lname in lnames: | |||
| return ns_id | |||
| e = "There is no namespace with name '{0}'.".format(name) | |||
| raise NamespaceNotFoundError(e) | |||
| def get_page(self, pagename): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| if pagename.startswith("Category:"): # proper namespace checking! | |||
| return get_category(pagename[9:]) | |||
| prefixes = self.namespace_id_to_name(NS_CATEGORY, all=True) | |||
| prefix = pagename.split(":", 1)[0] | |||
| if prefix != pagename: # avoid a page that is simply "Category" | |||
| if prefix in prefixes: | |||
| return Category(self, pagename) | |||
| return Page(self, pagename) | |||
| def get_category(self, catname): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return Category(self, "Category:" + catname) # namespace checking! | |||
| prefix = self.namespace_id_to_name(NS_CATEGORY) | |||
| pagename = "{0}:{1}".format(prefix, catname) | |||
| return Category(self, pagename) | |||
| def get_user(self, username): | |||
| """ | |||
| @@ -1,5 +1,6 @@ | |||
| # -*- coding: utf-8 -*- | |||
| from wiki.tools.constants import * | |||
| from wiki.tools.exceptions import UserNotFoundError | |||
| from wiki.tools.page import Page | |||
| @@ -12,9 +13,11 @@ class User(object): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| # Public attributes | |||
| self.site = site # Site instance, for doing API queries, etc | |||
| self.name = name # our username | |||
| # Site instance, for doing API queries, etc | |||
| self.site = site | |||
| # Username | |||
| self._name = name | |||
| # Attributes filled in by an API query | |||
| self._exists = None | |||
| @@ -34,19 +37,20 @@ class User(object): | |||
| if self._exists is None or force: | |||
| self._load_attributes_from_api() | |||
| if self._exists is False: | |||
| raise UserNotFoundError("User '{0}' does not exist.".format(self.name)) | |||
| e = "User '{0}' does not exist.".format(self._name) | |||
| raise UserNotFoundError(e) | |||
| return getattr(self, attr) | |||
| def _load_attributes_from_api(self): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| params = {"action": "query", "list": "users", "ususers": self.name, | |||
| params = {"action": "query", "list": "users", "ususers": self._name, | |||
| "usprop": "blockinfo|groups|rights|editcount|registration|emailable|gender"} | |||
| result = self.site.api_query(params) | |||
| # normalize our username in case it was entered oddly | |||
| self.name = result["query"]["users"][0]["name"] | |||
| self._name = result["query"]["users"][0]["name"] | |||
| try: | |||
| self._userid = result["query"]["users"][0]["userid"] | |||
| @@ -76,68 +80,78 @@ class User(object): | |||
| except KeyError: | |||
| self._blockinfo = False | |||
| def name(self, force=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return self._get_attribute_from_api("_name", force) | |||
| def exists(self, force=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return self._get_attribute_from_api("_exists", force) | |||
| def get_userid(self, force=False): | |||
| def userid(self, force=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return self._get_attribute_from_api("_userid", force) | |||
| def get_blockinfo(self, force=False): | |||
| def blockinfo(self, force=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return self._get_attribute_from_api("_blockinfo", force) | |||
| def get_groups(self, force=False): | |||
| def groups(self, force=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return self._get_attribute_from_api("_groups", force) | |||
| def get_rights(self, force=False): | |||
| def rights(self, force=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return self._get_attribute_from_api("_rights", force) | |||
| def get_editcount(self, force=False): | |||
| def editcount(self, force=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return self._get_attribute_from_api("_editcount", force) | |||
| def get_registration(self, force=False): | |||
| def registration(self, force=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return self._get_attribute_from_api("_registration", force) | |||
| def get_emailable(self, force=False): | |||
| def is_emailable(self, force=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return self._get_attribute_from_api("_emailable", force) | |||
| def get_gender(self, force=False): | |||
| def gender(self, force=False): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return self._get_attribute_from_api("_gender", force) | |||
| def get_userpage(self): | |||
| def userpage(self): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return Page(self.site, "User:" + self.name) # Namespace checking! | |||
| prefix = self.site.namespace_id_to_name(NS_USER) | |||
| pagename = "{0}:{1}".format(prefix, self._name) | |||
| return Page(self.site, pagename) | |||
| def get_talkpage(self): | |||
| def talkpage(self): | |||
| """ | |||
| Docstring needed | |||
| """ | |||
| return Page(self.site, "User talk:" + self.name) # Namespace checking! | |||
| prefix = self.site.namespace_id_to_name(NS_USER_TALK) | |||
| pagename = "{0}:{1}".format(prefix, self._name) | |||
| return Page(self.site, pagename) | |||