Skip to content

Commit 3010678

Browse files
LeMystCopilot
andauthored
Add support for additional request parameters in login methods (#865)
* Add support for additional request parameters in login methods * Refactor tests to use pytest.raises instead of unittest assertions * Update wikibaseintegrator/wbi_login.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Use filtered kwargs for all queries --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent a8f6898 commit 3010678

File tree

3 files changed

+41
-20
lines changed

3 files changed

+41
-20
lines changed

test/test_wbi_helpers.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import unittest
44

5+
import pytest
56
import requests
67

78
from wikibaseintegrator.wbi_config import config as wbi_config
@@ -15,22 +16,22 @@ def test_connection():
1516

1617
mediawiki_api_call_helper(data=data, max_retries=2, retry_after=1, allow_anonymous=True)
1718

18-
with unittest.TestCase().assertRaises(MaxRetriesReachedException):
19+
with pytest.raises(MaxRetriesReachedException):
1920
mediawiki_api_call_helper(data=data, mediawiki_api_url="https://www.wikidataaaaaaa.org", max_retries=2, retry_after=1, allow_anonymous=True)
2021

21-
with unittest.TestCase().assertRaises(MaxRetriesReachedException):
22+
with pytest.raises(MaxRetriesReachedException):
2223
mediawiki_api_call_helper(data=data, mediawiki_api_url=os.getenv("HTTPSTATUS_SERVICE", "https://httpbin.org") + "/status/500", max_retries=2, retry_after=1, allow_anonymous=True)
2324

24-
with unittest.TestCase().assertRaises(MaxRetriesReachedException):
25+
with pytest.raises(MaxRetriesReachedException):
2526
mediawiki_api_call_helper(data=data, mediawiki_api_url=os.getenv("HTTPSTATUS_SERVICE", "https://httpbin.org") + "/status/502", max_retries=2, retry_after=1, allow_anonymous=True)
2627

27-
with unittest.TestCase().assertRaises(MaxRetriesReachedException):
28+
with pytest.raises(MaxRetriesReachedException):
2829
mediawiki_api_call_helper(data=data, mediawiki_api_url=os.getenv("HTTPSTATUS_SERVICE", "https://httpbin.org") + "/status/503", max_retries=2, retry_after=1, allow_anonymous=True)
2930

30-
with unittest.TestCase().assertRaises(MaxRetriesReachedException):
31+
with pytest.raises(MaxRetriesReachedException):
3132
mediawiki_api_call_helper(data=data, mediawiki_api_url=os.getenv("HTTPSTATUS_SERVICE", "https://httpbin.org") + "/status/504", max_retries=2, retry_after=1, allow_anonymous=True)
3233

33-
with unittest.TestCase().assertRaises(requests.HTTPError):
34+
with pytest.raises(requests.HTTPError):
3435
mediawiki_api_call_helper(data=data, mediawiki_api_url=os.getenv("HTTPSTATUS_SERVICE", "https://httpbin.org") + "/status/400", max_retries=2, retry_after=1, allow_anonymous=True)
3536

3637

@@ -56,7 +57,7 @@ def test_user_agent(caplog):
5657
def test_allow_anonymous():
5758
wbi_config['USER_AGENT'] = 'WikibaseIntegrator-pytest/1.0 (test_wbi_helpers.py)'
5859
# Test there is a warning because of allow_anonymous
59-
with unittest.TestCase().assertRaises(ValueError):
60+
with pytest.raises(ValueError):
6061
mediawiki_api_call_helper(data={'format': 'json', 'action': 'wbgetentities', 'ids': 'Q42'}, max_retries=3, retry_after=1, user_agent='MyWikibaseBot/0.5')
6162

6263
# Test there is no warning because of allow_anonymous
@@ -84,7 +85,7 @@ def test_format2wbi():
8485
assert isinstance(format2wbi('property', '{}'), PropertyEntity)
8586
assert isinstance(format2wbi('lexeme', '{}'), LexemeEntity)
8687
assert isinstance(format2wbi('mediainfo', '{}'), MediaInfoEntity)
87-
with unittest.TestCase().assertRaises(ValueError):
88+
with pytest.raises(ValueError):
8889
format2wbi('unknown', '{}')
8990

9091
result = format2wbi('item', '''{

test/test_wbi_login.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import unittest
44

55
import pytest
6+
import requests
67
from oauthlib.oauth2 import MissingTokenError
78

89
from wikibaseintegrator import wbi_login
@@ -23,11 +24,11 @@
2324

2425

2526
def test_login():
26-
with unittest.TestCase().assertRaises(LoginError):
27+
with pytest.raises(LoginError):
2728
login = wbi_login.Clientlogin(user='wrong', password='wrong')
2829
login.generate_edit_credentials()
2930

30-
with unittest.TestCase().assertRaises(LoginError):
31+
with pytest.raises(LoginError):
3132
login = wbi_login.Login(user='wrong', password='wrong')
3233
login.generate_edit_credentials()
3334

@@ -38,8 +39,16 @@ def test_login():
3839
print("no WDUSER or WDPASS found in environment variables", file=sys.stderr)
3940

4041

42+
def test_verify():
43+
with pytest.raises(requests.exceptions.SSLError):
44+
wbi_login.Clientlogin(user='wrong', password='wrong', mediawiki_api_url='https://self-signed.badssl.com/', verify=True)
45+
46+
with pytest.raises(requests.exceptions.JSONDecodeError):
47+
wbi_login.Clientlogin(user='wrong', password='wrong', mediawiki_api_url='https://self-signed.badssl.com/', verify=False)
48+
49+
4150
def test_oauth1():
42-
with unittest.TestCase().assertRaises(LoginError):
51+
with pytest.raises(LoginError):
4352
login = wbi_login.OAuth1(consumer_token='wrong', consumer_secret='wrong')
4453
login.generate_edit_credentials()
4554

@@ -50,7 +59,7 @@ def test_oauth1():
5059

5160

5261
def test_oauth1_access():
53-
with unittest.TestCase().assertRaises(LoginError):
62+
with pytest.raises(LoginError):
5463
login = wbi_login.OAuth1(consumer_token='wrong', consumer_secret='wrong', access_token='wrong', access_secret='wrong')
5564
login.generate_edit_credentials()
5665

wikibaseintegrator/wbi_login.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import logging
55
import time
66
import webbrowser
7-
from typing import Optional
7+
from typing import Any, Optional
88

99
from mwoauth import ConsumerToken, Handshaker, OAuthException
1010
from oauthlib.oauth2 import BackendApplicationClient, InvalidClientError
@@ -199,7 +199,7 @@ def continue_oauth(self, oauth_callback_data: Optional[str] = None) -> None:
199199

200200
class Login(_Login):
201201
@wbi_backoff()
202-
def __init__(self, user: Optional[str] = None, password: Optional[str] = None, mediawiki_api_url: Optional[str] = None, token_renew_period: int = 1800, user_agent: Optional[str] = None):
202+
def __init__(self, user: Optional[str] = None, password: Optional[str] = None, mediawiki_api_url: Optional[str] = None, token_renew_period: int = 1800, user_agent: Optional[str] = None, **kwargs: Any):
203203
"""
204204
This class is used to log in with a bot password
205205
@@ -208,6 +208,7 @@ def __init__(self, user: Optional[str] = None, password: Optional[str] = None, m
208208
:param mediawiki_api_url: The URL to the MediaWiki API (default Wikidata)
209209
:param token_renew_period: Seconds after which a new token should be requested from the Wikidata server
210210
:param user_agent: UA string to use for API requests.
211+
:param kwargs: Additional parameters to pass to the requests.sessions.Session.post method, such as headers or proxies.
211212
"""
212213

213214
mediawiki_api_url = str(mediawiki_api_url or config['MEDIAWIKI_API_URL'])
@@ -225,9 +226,13 @@ def __init__(self, user: Optional[str] = None, password: Optional[str] = None, m
225226
'User-Agent': get_user_agent(user_agent)
226227
}
227228

228-
# get login token
229-
login_token = session.post(mediawiki_api_url, data=params_login, headers=headers).json()['query']['tokens']['logintoken']
229+
allowed_kwargs = {'headers', 'proxies', 'timeout', 'verify'}
230+
filtered_kwargs = {key: value for key, value in kwargs.items() if key in allowed_kwargs}
231+
if len(filtered_kwargs) < len(kwargs):
232+
log.warning("Unsupported kwargs were ignored: %s", set(kwargs) - allowed_kwargs)
230233

234+
# get login token
235+
login_token = session.post(mediawiki_api_url, data=params_login, headers=headers, **filtered_kwargs).json()['query']['tokens']['logintoken']
231236
params = {
232237
'action': 'login',
233238
'lgname': user,
@@ -236,7 +241,7 @@ def __init__(self, user: Optional[str] = None, password: Optional[str] = None, m
236241
'format': 'json'
237242
}
238243

239-
login_result = session.post(mediawiki_api_url, data=params, headers=headers).json()
244+
login_result = session.post(mediawiki_api_url, data=params, headers=headers, **filtered_kwargs).json()
240245

241246
if 'login' in login_result and login_result['login']['result'] == 'Success':
242247
log.info("Successfully logged in as %s", login_result['login']['lgusername'])
@@ -253,7 +258,7 @@ def __init__(self, user: Optional[str] = None, password: Optional[str] = None, m
253258

254259
class Clientlogin(_Login):
255260
@wbi_backoff()
256-
def __init__(self, user: Optional[str] = None, password: Optional[str] = None, mediawiki_api_url: Optional[str] = None, token_renew_period: int = 1800, user_agent: Optional[str] = None):
261+
def __init__(self, user: Optional[str] = None, password: Optional[str] = None, mediawiki_api_url: Optional[str] = None, token_renew_period: int = 1800, user_agent: Optional[str] = None, **kwargs: Any):
257262
"""
258263
This class is used to log in with a user account
259264
@@ -262,6 +267,7 @@ def __init__(self, user: Optional[str] = None, password: Optional[str] = None, m
262267
:param mediawiki_api_url: The URL to the MediaWiki API (default Wikidata)
263268
:param token_renew_period: Seconds after which a new token should be requested from the Wikidata server
264269
:param user_agent: UA string to use for API requests.
270+
:param kwargs: Additional parameters to pass to the requests.sessions.Session.post method, such as headers or proxies.
265271
"""
266272

267273
mediawiki_api_url = str(mediawiki_api_url or config['MEDIAWIKI_API_URL'])
@@ -279,8 +285,13 @@ def __init__(self, user: Optional[str] = None, password: Optional[str] = None, m
279285
'User-Agent': get_user_agent(user_agent)
280286
}
281287

288+
allowed_kwargs = {'headers', 'proxies', 'timeout', 'verify'}
289+
filtered_kwargs = {key: value for key, value in kwargs.items() if key in allowed_kwargs}
290+
if len(filtered_kwargs) < len(kwargs):
291+
log.warning("Unsupported kwargs were ignored: %s", set(kwargs) - allowed_kwargs)
292+
282293
# get login token
283-
login_token = session.post(mediawiki_api_url, data=params_login, headers=headers).json()['query']['tokens']['logintoken']
294+
login_token = session.post(mediawiki_api_url, data=params_login, headers=headers, **filtered_kwargs).json()['query']['tokens']['logintoken']
284295

285296
params = {
286297
'action': 'clientlogin',
@@ -291,7 +302,7 @@ def __init__(self, user: Optional[str] = None, password: Optional[str] = None, m
291302
'format': 'json'
292303
}
293304

294-
login_result = session.post(mediawiki_api_url, data=params, headers=headers).json()
305+
login_result = session.post(mediawiki_api_url, data=params, headers=headers, **filtered_kwargs).json()
295306

296307
log.debug(login_result)
297308

0 commit comments

Comments
 (0)