Skip to content

Commit

Permalink
MediaWiki login (#60)
Browse files Browse the repository at this point in the history
* add support for login
* add login tests
  • Loading branch information
barrust committed Nov 20, 2018
1 parent 10feaf4 commit 92dd95f
Show file tree
Hide file tree
Showing 13 changed files with 336,126 additions and 332,125 deletions.
15 changes: 10 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
language: python
python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
matrix:
include:
- python: 2.7
- python: 3.3
- python: 3.4
- python: 3.5
- python: 3.6
- python: 3.7
dist: xenial
sudo: true

# install python dependencies including this package in the travis
# virtualenv
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# MediaWiki Changelog

## Current Version

* Add support for logging into the MediaWiki site

## Version 0.4.1

* Default to `https`
Expand Down
1 change: 1 addition & 0 deletions docs/source/code.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ MediaWiki
memoized, clear_memoized, refresh_interval, set_api_url,
supported_languages, random, categorytree, page, wiki_request

.. automethod:: mediawiki.MediaWiki.login(username, password)
.. automethod:: mediawiki.MediaWiki.suggest(query)
.. automethod:: mediawiki.MediaWiki.search(query, results=10, suggestion=False)
.. automethod:: mediawiki.MediaWiki.summary(title, sentences=0, chars=0, auto_suggest=True, redirect=True)
Expand Down
4 changes: 2 additions & 2 deletions mediawiki/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from .exceptions import (MediaWikiException, PageError, MediaWikiGeoCoordError,
RedirectError, DisambiguationError,
MediaWikiAPIURLError, HTTPTimeoutError,
MediaWikiCategoryTreeError)
MediaWikiCategoryTreeError, MediaWikiLoginError)

__author__ = 'Tyler Barrus'
__maintainer__ = 'Tyler Barrus'
Expand All @@ -21,4 +21,4 @@
__all__ = ['MediaWiki', 'PageError', 'RedirectError', 'MediaWikiException',
'DisambiguationError', 'MediaWikiAPIURLError',
'HTTPTimeoutError', 'MediaWikiGeoCoordError',
'MediaWikiCategoryTreeError']
'MediaWikiCategoryTreeError', 'MediaWikiLoginError']
16 changes: 16 additions & 0 deletions mediawiki/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,19 @@ def category(self):
""" str: The category that threw an exception during category tree \
generation """
return self._category


class MediaWikiLoginError(MediaWikiBaseException):
''' Exception raised when unable to login to the MediaWiki site
Args:
error (str): The error message that the MediaWiki site returned '''

def __init__(self, error):
self._error = error
super(MediaWikiLoginError, self).__init__(error)

@property
def error(self):
""" str: The error message that the MediaWiki site returned """
return self._error
69 changes: 66 additions & 3 deletions mediawiki/mediawiki.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import requests
from .exceptions import (MediaWikiException, PageError, MediaWikiAPIURLError,
HTTPTimeoutError, MediaWikiGeoCoordError,
MediaWikiCategoryTreeError)
MediaWikiCategoryTreeError, MediaWikiLoginError)
from .mediawikipage import (MediaWikiPage)
from .utilities import (memoize)

Expand Down Expand Up @@ -70,6 +70,9 @@ def __init__(self, url='https://{lang}.wikipedia.org/w/api.php', lang='en',
self._refresh_interval = None
self._use_cache = True

# for login information
self._is_logged_in = False

# call helper functions to get everything set up
self._reset_session()
try:
Expand Down Expand Up @@ -250,6 +253,53 @@ def refresh_interval(self, refresh_interval):
else:
self._refresh_interval = None

def login(self, username, password, strict=True):
''' Login as specified user
Args:
username (str): The username to log in with
password (str): The password for the user
strict (bool): `True` to thow an error on failure
Returns:
bool: `True` if successfully logged in; `False` otherwise
Raises:
:py:func:`mediawiki.exceptions.MediaWikiLoginError`: if \
unable to login
Note:
Per the MediaWiki API, one should use the `bot password`; \
see https://www.mediawiki.org/wiki/API:Login for more \
information '''
# get login token
params = {
'action': 'query',
'meta': 'tokens',
'type': 'login',
'format': 'json'
}
token_res = self._get_response(params)
if 'query' in token_res and 'tokens' in token_res['query']:
token = token_res['query']['tokens']['logintoken']

params = {
'action': 'login',
'lgname': username,
'lgpassword': password,
'lgtoken': token,
'format': 'json'
}

res = self._post_response(params)
if res['login']['result'] == 'Success':
self._is_logged_in = True
return True
self._is_logged_in = False
reason = res['login']['reason']
if strict:
msg = "MediaWiki login failure: {}".format(reason)
raise MediaWikiLoginError(msg)
return False

# non-properties
def set_api_url(self, api_url='https://{lang}.wikipedia.org/w/api.php',
lang='en'):
Expand All @@ -259,8 +309,8 @@ def set_api_url(self, api_url='https://{lang}.wikipedia.org/w/api.php',
api_url (str): API URL to use
lang (str): Language of the API URL
Raises:
`mediawiki.exceptions.MediaWikiAPIURLError`: if the url is \
not a valid MediaWiki site '''
:py:func:`mediawiki.exceptions.MediaWikiAPIURLError`: if the \
url is not a valid MediaWiki site '''
old_api_url = self._api_url
old_lang = self._lang
self._lang = lang.lower()
Expand All @@ -280,6 +330,7 @@ def _reset_session(self):
headers = {'User-Agent': self._user_agent}
self._session = requests.Session()
self._session.headers.update(headers)
self._is_logged_in = False

def clear_memoized(self):
''' Clear memoized (cached) values '''
Expand All @@ -301,6 +352,11 @@ def supported_languages(self):
self.__supported_languages = supported
return self.__supported_languages

@property
def logged_in(self):
''' bool: Returns if logged into the MediaWiki site '''
return self._is_logged_in

def random(self, pages=1):
''' Request a random page title or list of random titles
Expand Down Expand Up @@ -643,6 +699,8 @@ def __cat_tree_rec(cat, depth, tree, level, categories, links):
except PageError:
raise PageError('{0}:{1}'.format(self.category_prefix,
cat))
except KeyboardInterrupt:
raise
except Exception:
tries = tries + 1
time.sleep(1)
Expand Down Expand Up @@ -829,4 +887,9 @@ def _get_response(self, params):
return self._session.get(self._api_url, params=params,
timeout=self._timeout).json(encoding='utf8')

def _post_response(self, params):
''' wrap a post call to the requests package '''
return self._session.post(self._api_url, data=params,
timeout=self._timeout).json(encoding='utf8')

# end MediaWiki class
12 changes: 7 additions & 5 deletions mediawiki/mediawikipage.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ class MediaWikiPage(object):
original_title (str): Not to be used from the caller; used to \
help follow redirects
Raises:
`mediawiki.exceptions.PageError`: if page provided does not exist
:py:func:`mediawiki.exceptions.PageError`: if page provided does \
not exist
Raises:
`mediawiki.exceptions.DisambiguationError`: if page provided \
is a disambiguation page
:py:func:`mediawiki.exceptions.DisambiguationError`: if page \
provided is a disambiguation page
Raises:
`mediawiki.exceptions.RedirectError`: if redirect is **False** \
and the pageid or title provided redirects to another page
:py:func:`mediawiki.exceptions.RedirectError`: if redirect is \
**False** and the pageid or title provided redirects to another \
page
Warning:
This should never need to be used directly! Please use \
:func:`mediawiki.MediaWiki.page` '''
Expand Down
11 changes: 11 additions & 0 deletions scripts/generate_test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ def _get_response(self, params):
''' overloaded response '''
return MediaWiki._get_response(self, params)

@capture_response
def _post_response(self, params):
''' overloaded response '''
return MediaWiki._post_response(self, params)


PULL_ALL = False

Expand All @@ -82,6 +87,7 @@ def _get_response(self, params):
PULL_LOGOS = False
PULL_HATNOTES = False
PULL_SECTION_LINKS = False
PULL_LOGIN = False

# regression tests
PULL_ISSUE_15 = False
Expand Down Expand Up @@ -422,6 +428,11 @@ def _get_response(self, params):

print("Completed pulling the section links")

if PULL_ALL is True or PULL_LOGIN is True:
pg = wikipedia.login(username='badusername', password='fakepassword')
print("Completed pulling login")


if PULL_ALL is True or PULL_ISSUE_14 is True:
res = site.page('One Two Three... Infinity').images
responses[wikipedia.api_url]['hidden_images'] = res
Expand Down
6 changes: 6 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
[bdist_wheel]
universal=1

[pep8]
max-line-length=120

[pycodestyle]
max-line-length = 120
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ def read_file(filepath):
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6'
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
],
test_suite = 'tests'
)

0 comments on commit 92dd95f

Please sign in to comment.