From a515a004c87526960e0aa297bf5a41a0224de771 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Tue, 2 Aug 2011 15:50:59 -0400 Subject: [PATCH] Docstrings for everything in User, cleaned stuff up a bit. --- wiki/tools/functions.py | 14 +++- wiki/tools/user.py | 189 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 138 insertions(+), 65 deletions(-) diff --git a/wiki/tools/functions.py b/wiki/tools/functions.py index bc7b187..ab18609 100644 --- a/wiki/tools/functions.py +++ b/wiki/tools/functions.py @@ -165,9 +165,17 @@ def get_site(name=None, project=None, lang=None): raise SiteNotFoundError(e) def add_site(): - """STUB: config editing is required first""" + """STUB: config editing is required first. + + Returns True if the site was added successfully or False if the site was + already in our config. Raises ConfigError if saving the updated file failed + for some reason.""" pass -def del_site(): - """STUB: config editing is required first""" +def del_site(name): + """STUB: config editing is required first. + + Returns True if the site was removed successfully or False if the site was + not in our config originally. Raises ConfigError if saving the updated file + failed for some reason.""" pass diff --git a/wiki/tools/user.py b/wiki/tools/user.py index be71515..16919e1 100644 --- a/wiki/tools/user.py +++ b/wiki/tools/user.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +from time import strptime + from wiki.tools.constants import * from wiki.tools.exceptions import UserNotFoundError from wiki.tools.page import Page @@ -7,34 +9,53 @@ from wiki.tools.page import Page class User(object): """ EarwigBot's Wiki Toolset: User Class + + Represents a User on a given Site. Has methods for getting a bunch of + information about the user, such as editcount and user rights, methods for + returning the user's userpage and talkpage, etc. + + Public methods: + name -- returns the user's username + exists -- returns True if the user exists, False if they do not + userid -- returns an integer ID representing the user + blockinfo -- returns information about a current block on the user + groups -- returns a list of the user's groups + rights -- returns a list of the user's rights + editcount -- returns the number of edits made by the user + registration -- returns the time the user registered as a time.struct_time + emailable -- returns True if you can email the user, False if you cannot + gender -- returns the user's gender ("male", "female", or "unknown") + get_userpage -- returns a Page object representing the user's userpage + get_talkpage -- returns a Page object representing the user's talkpage """ def __init__(self, site, name): - """ - Docstring needed - """ - # Site instance, for doing API queries, etc - self.site = site + """Constructor for new User instances. - # Username - self._name = name + Takes two arguments, a Site object (necessary for doing API queries), + and the name of the user, preferably without "User:" in front, although + this prefix will be automatically removed by the API if given. - # Attributes filled in by an API query - self._exists = None - self._userid = None - self._blockinfo = None - self._groups = None - self._rights = None - self._editcount = None - self._registration = None - self._emailable = None - self._gender = None + You can also use site.get_user() instead, which returns a User object, + and is preferred. - def _get_attribute(self, attr, force): + We won't do any API queries yet for basic information about the user - + save that for when the information is requested. """ - Docstring needed + self._site = site + self._name = name + + def _get_attribute(self, attr, force): + """Internally used to get an attribute by name. + + We'll call _load_attributes() to get this (and all other attributes) + from the API if it is not already defined. If `force` is True, we'll + re-load them even if they've already been loaded. + + Raises UserNotFoundError if a nonexistant user prevents us from + returning a certain attribute. """ - if self._exists is None or force: + if not hasattr(self, attr) or force: self._load_attributes() if self._exists is False: e = "User '{0}' does not exist.".format(self._name) @@ -42,30 +63,42 @@ class User(object): return getattr(self, attr) def _load_attributes(self): - """ - Docstring needed + """Internally used to load all attributes from the API. + + Normally, this is called by _get_attribute() when a requested attribute + is not defined. This defines it. """ params = {"action": "query", "list": "users", "ususers": self._name, "usprop": "blockinfo|groups|rights|editcount|registration|emailable|gender"} - result = self.site.api_query(params) + result = self._site.api_query(params) + res = result["query"]["users"][0] # normalize our username in case it was entered oddly - self._name = result["query"]["users"][0]["name"] + self._name = res["name"] try: - self._userid = result["query"]["users"][0]["userid"] + self._userid = res["userid"] except KeyError: # userid is missing, so user does not exist self._exists = False return self._exists = True - res = result['query']['users'][0] + + try: + self._blockinfo = { + "by": res["blockedby"], + "reason": res["blockreason"], + "expiry": res["blockexpiry"] + } + except KeyError: + self._blockinfo = False self._groups = res["groups"] - self._rights = res["rights"] + self._rights = res["rights"].values() self._editcount = res["editcount"] - self._registration = res["registration"] - self._gender = res["gender"] + + reg = res["registration"] + self._registration = strptime(reg, "%Y-%m-%dT%H:%M:%SZ") try: res["emailable"] @@ -74,88 +107,120 @@ class User(object): else: self._emailable = True - try: - self._blockinfo = {"by": res["blockedby"], - "reason": res["blockreason"], "expiry": res["blockexpiry"]} - except KeyError: - self._blockinfo = False + self._gender = res["gender"] def name(self, force=False): - """ - Docstring needed + """Returns the user's name. + + If `force` is True, we will load the name from the API and return that. + This could potentially return a "normalized" version of the name - for + example, without a "User:" prefix or without underscores. Unlike other + attribute getters, this will never make an API query without `force`. + + Note that if another attribute getter, like exists(), has already been + called, then the username has already been normalized. """ if force: self._load_attributes() return self._name def exists(self, force=False): - """ - Docstring needed + """Returns True if the user exists, or False if they do not. + + Makes an API query if `force` is True or if we haven't made one + already. """ if self._exists is None or force: self._load_attributes() return self._exists def userid(self, force=False): - """ - Docstring needed + """Returns an integer ID used by MediaWiki to represent the user. + + Raises UserNotFoundError if the user does not exist. Makes an API query + if `force` is True or if we haven't made one already. """ return self._get_attribute("_userid", force) def blockinfo(self, force=False): - """ - Docstring needed + """Returns information about a current block on the user. + + If the user is not blocked, returns False. If they are, returns a dict + with three keys: "by" is the blocker's username, "reason" is the reason + why they were blocked, and "expiry" is when the block expires. + + Raises UserNotFoundError if the user does not exist. Makes an API query + if `force` is True or if we haven't made one already. """ return self._get_attribute("_blockinfo", force) def groups(self, force=False): - """ - Docstring needed + """Returns a list of groups this user is in, including "*". + + Raises UserNotFoundError if the user does not exist. Makes an API query + if `force` is True or if we haven't made one already. """ return self._get_attribute("_groups", force) def rights(self, force=False): - """ - Docstring needed + """Returns a list of this user's rights. + + Raises UserNotFoundError if the user does not exist. Makes an API query + if `force` is True or if we haven't made one already. """ return self._get_attribute("_rights", force) def editcount(self, force=False): - """ - Docstring needed + """Returns the number of edits made by the user. + + Raises UserNotFoundError if the user does not exist. Makes an API query + if `force` is True or if we haven't made one already. """ return self._get_attribute("_editcount", force) def registration(self, force=False): - """ - Docstring needed + """Returns the time the user registered as a time.struct_time object. + + Raises UserNotFoundError if the user does not exist. Makes an API query + if `force` is True or if we haven't made one already. """ return self._get_attribute("_registration", force) def emailable(self, force=False): - """ - Docstring needed + """Returns True if the user can be emailed, or False if they cannot. + + Raises UserNotFoundError if the user does not exist. Makes an API query + if `force` is True or if we haven't made one already. """ return self._get_attribute("_emailable", force) def gender(self, force=False): - """ - Docstring needed + """Returns the user's gender. + + Can return either "male", "female", or "unknown", if they did not + specify it. + + Raises UserNotFoundError if the user does not exist. Makes an API query + if `force` is True or if we haven't made one already. """ return self._get_attribute("_gender", force) def get_userpage(self): + """Returns a Page object representing the user's userpage. + + No checks are made to see if it exists or not. Proper site namespace + conventions are followed. """ - Docstring needed - """ - prefix = self.site.namespace_id_to_name(NS_USER) + prefix = self._site.namespace_id_to_name(NS_USER) pagename = ''.join((prefix, ":", self._name)) - return Page(self.site, pagename) + return Page(self._site, pagename) def get_talkpage(self): + """Returns a Page object representing the user's talkpage. + + No checks are made to see if it exists or not. Proper site namespace + conventions are followed. """ - Docstring needed - """ - prefix = self.site.namespace_id_to_name(NS_USER_TALK) + prefix = self._site.namespace_id_to_name(NS_USER_TALK) pagename = ''.join((prefix, ":", self._name)) - return Page(self.site, pagename) + return Page(self._site, pagename)