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) |