Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MediaWiki login #60

Merged
merged 5 commits into from
Nov 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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'
)
Loading