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

HTTP basic auth: encode username and password as UTF-8 (#315) #316

Merged
merged 1 commit into from
Jan 28, 2024
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
13 changes: 11 additions & 2 deletions mwclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ class Site:
do_init (bool): Whether to automatically initialize the :py:class:`Site` on
initialization. When set to `False`, the :py:class:`Site` must be initialized
manually using the :py:meth:`.site_init` method. Defaults to `True`.
httpauth (Union[tuple[str, str], requests.auth.AuthBase]): An
httpauth (Union[tuple[basestring, basestring], requests.auth.AuthBase]): An
authentication method to be used when making API requests. This can be either
an authentication object as provided by the :py:mod:`requests` library, or a
tuple in the form `{username, password}`.
tuple in the form `{username, password}`. Usernames and passwords provided as
text strings are encoded as UTF-8. If dealing with a server that cannot
handle UTF-8, please provide the username and password already encoded with
the appropriate encoding.
reqs (Dict[str, Any]): Additional arguments to be passed to the
:py:meth:`requests.Session.request` method when performing API calls. If the
`timeout` key is empty, a default timeout of 30 seconds is added.
Expand Down Expand Up @@ -109,6 +112,12 @@ def __init__(self, host, path='/w/', ext='.php', pool=None, retry_timeout=30,
if consumer_token is not None:
auth = OAuth1(consumer_token, consumer_secret, access_token, access_secret)
elif isinstance(httpauth, (list, tuple)):
# workaround weird requests default to encode as latin-1
# https://github.com/mwclient/mwclient/issues/315
# https://github.com/psf/requests/issues/4564
httpauth = [
it.encode("utf-8") if isinstance(it, str) else it for it in httpauth
]
auth = HTTPBasicAuth(*httpauth)
elif httpauth is None or isinstance(httpauth, (AuthBase,)):
auth = httpauth
Expand Down
9 changes: 9 additions & 0 deletions test/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ def test_httpauth_defaults_to_basic_auth(self):

assert isinstance(site.connection.auth, requests.auth.HTTPBasicAuth)

@responses.activate
def test_basic_auth_non_latin(self):

self.httpShouldReturn(self.metaResponseAsJson())

site = mwclient.Site('test.wikipedia.org', httpauth=('我', '非常秘密'))

assert isinstance(site.connection.auth, requests.auth.HTTPBasicAuth)

@responses.activate
def test_httpauth_raise_error_on_invalid_type(self):

Expand Down