Ver a proveniência

Cleanup; fix site locking mechanism; badtoken handling.

tags/v0.2
Ben Kurtovic há 11 anos
ascendente
cometimento
4fff908912
2 ficheiros alterados com 20 adições e 20 eliminações
  1. +13
    -6
      earwigbot/wiki/page.py
  2. +7
    -14
      earwigbot/wiki/site.py

+ 13
- 6
earwigbot/wiki/page.py Ver ficheiro

@@ -280,8 +280,7 @@ class Page(CopyvioMixIn):
self._assert_existence()

def _edit(self, params=None, text=None, summary=None, minor=None, bot=None,
force=None, section=None, captcha_id=None, captcha_word=None,
tries=0):
force=None, section=None, captcha_id=None, captcha_word=None):
"""Edit the page!

If *params* is given, we'll use it as our API query parameters.
@@ -316,7 +315,7 @@ class Page(CopyvioMixIn):
except exceptions.APIError as error:
if not hasattr(error, "code"):
raise # We can only handle errors with a code attribute
result = self._handle_edit_errors(error, params, tries)
result = self._handle_edit_errors(error, params)

# If everything was successful, reset invalidated attributes:
if result["edit"]["result"] == "Success":
@@ -360,12 +359,12 @@ class Page(CopyvioMixIn):

return params

def _handle_edit_errors(self, error, params, tries):
def _handle_edit_errors(self, error, params, retry=True):
"""If our edit fails due to some error, try to handle it.

We'll either raise an appropriate exception (for example, if the page
is protected), or we'll try to fix it (for example, if we can't edit
due to being logged out, we'll try to log in).
is protected), or we'll try to fix it (for example, if the token is
invalid, we'll try to get a new one).
"""
perms = ["noedit", "noedit-anon", "cantcreate", "cantcreate-anon",
"protectedtitle", "noimageredirect", "noimageredirect-anon",
@@ -378,6 +377,14 @@ class Page(CopyvioMixIn):
self._basetimestamp = None
self._exists = self.PAGE_UNKNOWN
raise exceptions.EditConflictError(error.info)
elif error.code == "badtoken" and retry:
params["token"] = self.site.get_token("edit")
try:
return self.site.api_query(**params)
except exceptions.APIError as error:
if not hasattr(error, "code"):
raise # We can only handle errors with a code attribute
result = self._handle_edit_errors(error, params, retry=False)
elif error.code in ["emptypage", "emptynewsection"]:
raise exceptions.NoContentError(error.info)
elif error.code == "contenttoobig":


+ 7
- 14
earwigbot/wiki/site.py Ver ficheiro

@@ -26,7 +26,7 @@ from json import loads
from logging import getLogger, NullHandler
from os.path import expanduser
from StringIO import StringIO
from threading import Lock
from threading import RLock
from time import sleep, time
from urllib import quote_plus, unquote_plus
from urllib2 import build_opener, HTTPCookieProcessor, URLError
@@ -124,7 +124,7 @@ class Site(object):
self._wait_between_queries = wait_between_queries
self._max_retries = 6
self._last_query_time = 0
self._api_lock = Lock()
self._api_lock = RLock()
self._api_info_cache = {"maxlag": 0, "lastcheck": 0}

# Attributes used for SQL queries:
@@ -133,7 +133,7 @@ class Site(object):
else:
self._sql_data = {}
self._sql_conn = None
self._sql_lock = Lock()
self._sql_lock = RLock()
self._sql_info_cache = {"replag": 0, "lastcheck": 0, "usable": None}

# Attribute used in copyright violation checks (see CopyrightMixIn):
@@ -298,7 +298,7 @@ class Site(object):
# Try to log in if we got logged out:
self._login(self._login_info)
if "token" in params: # Fetch a new one; this is invalid now
params["token"] = self.get_token(params["action"], False)
params["token"] = self.get_token(params["action"])
return self._api_query(params, tries, wait, ae_retry=False)
if not all(self._login_info):
e = "Assertion failed, and no login info was provided."
@@ -762,27 +762,20 @@ class Site(object):
result = list(self.sql_query(query))
return int(result[0][0])

def get_token(self, action, lock=True):
def get_token(self, action):
"""Return a token for a data-modifying API action.

*action* must be one of the types listed on
<https://www.mediawiki.org/wiki/API:Tokens>. If it's given as a union
of types separated by |, then the function will return a dictionary
of tokens instead of a single one. *lock* is for internal usage;
setting it to ``False`` prevents the query from acquiring the internal
API access lock.
of tokens instead of a single one.

Raises :py:exc:`~earwigbot.exceptions.PermissionsError` if we don't
have permissions for the requested action(s), or they are invalid.
Raises :py:exc:`~earwigbot.exceptions.APIError` if there was some other
API issue.
"""
if lock:
res = self.api_query(action="tokens", type=action)
else:
params = {"action": "tokens", "type": action}
res = self._api_query(params, ae_retry=False)

res = self.api_query(action="tokens", type=action)
if "warnings" in res and "tokens" in res["warnings"]:
raise exceptions.PermissionsError(res["warnings"]["tokens"]["*"])
if "|" in action:


Carregando…
Cancelar
Guardar