Skip to content

Commit 6a53852

Browse files
authored
Hide internals (#79)
1 parent cbe65d7 commit 6a53852

34 files changed

+1707
-1475
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
### Added
99
- Adding explicit support for Python `3.12`.
1010

11+
### Changed
12+
- Except for `requests_auth.testing`, only direct access via `requests_auth.` was considered publicly exposed. This is now explicit, as inner packages are now using private prefix (`_`).
13+
If you were relying on some classes or functions that are now internal, feel free to open an issue.
14+
15+
### Fixed
16+
- Type information is now provided following [PEP 561](https://www.python.org/dev/peps/pep-0561/)
17+
1118
### Removed
1219
- Removing support for Python `3.7`.
1320

requests_auth/__init__.py

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,36 @@
1-
from requests_auth.authentication import (
1+
from requests_auth._authentication import (
22
Basic,
33
HeaderApiKey,
44
QueryApiKey,
55
NTLM,
66
Auths,
7-
OAuth2,
7+
)
8+
from requests_auth._oauth2.common import OAuth2
9+
from requests_auth._oauth2.authorization_code import (
10+
OAuth2AuthorizationCode,
11+
OktaAuthorizationCode,
12+
)
13+
from requests_auth._oauth2.authorization_code_pkce import (
814
OAuth2AuthorizationCodePKCE,
915
OktaAuthorizationCodePKCE,
16+
)
17+
from requests_auth._oauth2.client_credentials import (
18+
OAuth2ClientCredentials,
19+
OktaClientCredentials,
20+
)
21+
from requests_auth._oauth2.implicit import (
1022
OAuth2Implicit,
1123
OktaImplicit,
1224
OktaImplicitIdToken,
1325
AzureActiveDirectoryImplicit,
1426
AzureActiveDirectoryImplicitIdToken,
15-
OAuth2AuthorizationCode,
16-
OktaAuthorizationCode,
17-
OAuth2ClientCredentials,
18-
OktaClientCredentials,
27+
)
28+
from requests_auth._oauth2.resource_owner_password import (
1929
OAuth2ResourceOwnerPasswordCredentials,
2030
OktaResourceOwnerPasswordCredentials,
2131
)
22-
from requests_auth.oauth2_tokens import JsonTokenFileCache
23-
from requests_auth.errors import (
32+
from requests_auth._oauth2.tokens import JsonTokenFileCache
33+
from requests_auth._errors import (
2434
GrantNotProvided,
2535
TimeoutOccurred,
2636
AuthenticationFailed,
@@ -30,3 +40,34 @@
3040
InvalidGrantRequest,
3141
)
3242
from requests_auth.version import __version__
43+
44+
__all__ = [
45+
"Basic",
46+
"HeaderApiKey",
47+
"QueryApiKey",
48+
"OAuth2",
49+
"OAuth2AuthorizationCodePKCE",
50+
"OktaAuthorizationCodePKCE",
51+
"OAuth2Implicit",
52+
"OktaImplicit",
53+
"OktaImplicitIdToken",
54+
"AzureActiveDirectoryImplicit",
55+
"AzureActiveDirectoryImplicitIdToken",
56+
"OAuth2AuthorizationCode",
57+
"OktaAuthorizationCode",
58+
"OAuth2ClientCredentials",
59+
"OktaClientCredentials",
60+
"OAuth2ResourceOwnerPasswordCredentials",
61+
"OktaResourceOwnerPasswordCredentials",
62+
"NTLM",
63+
"Auths",
64+
"JsonTokenFileCache",
65+
"GrantNotProvided",
66+
"TimeoutOccurred",
67+
"AuthenticationFailed",
68+
"StateNotProvided",
69+
"InvalidToken",
70+
"TokenExpiryNotProvided",
71+
"InvalidGrantRequest",
72+
"__version__",
73+
]

requests_auth/_authentication.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
from urllib.parse import parse_qs, urlsplit, urlunsplit, urlencode
2+
3+
import requests
4+
import requests.auth
5+
import warnings
6+
7+
8+
class SupportMultiAuth:
9+
"""Inherit from this class to be able to use your class with requests_auth provided authentication classes."""
10+
11+
def __add__(self, other):
12+
if isinstance(other, _MultiAuth):
13+
return _MultiAuth(self, *other.authentication_modes)
14+
return _MultiAuth(self, other)
15+
16+
def __and__(self, other):
17+
if isinstance(other, _MultiAuth):
18+
return _MultiAuth(self, *other.authentication_modes)
19+
return _MultiAuth(self, other)
20+
21+
22+
class HeaderApiKey(requests.auth.AuthBase, SupportMultiAuth):
23+
"""Describes an API Key requests authentication."""
24+
25+
def __init__(self, api_key: str, header_name: str = None):
26+
"""
27+
:param api_key: The API key that will be sent.
28+
:param header_name: Name of the header field. "X-API-Key" by default.
29+
"""
30+
self.api_key = api_key
31+
if not api_key:
32+
raise Exception("API Key is mandatory.")
33+
self.header_name = header_name or "X-API-Key"
34+
35+
def __call__(self, r):
36+
r.headers[self.header_name] = self.api_key
37+
return r
38+
39+
40+
class QueryApiKey(requests.auth.AuthBase, SupportMultiAuth):
41+
"""Describes an API Key requests authentication."""
42+
43+
def __init__(self, api_key: str, query_parameter_name: str = None):
44+
"""
45+
:param api_key: The API key that will be sent.
46+
:param query_parameter_name: Name of the query parameter. "api_key" by default.
47+
"""
48+
self.api_key = api_key
49+
if not api_key:
50+
raise Exception("API Key is mandatory.")
51+
self.query_parameter_name = query_parameter_name or "api_key"
52+
53+
def __call__(self, r):
54+
r.url = _add_parameters(r.url, {self.query_parameter_name: self.api_key})
55+
return r
56+
57+
58+
class Basic(requests.auth.HTTPBasicAuth, SupportMultiAuth):
59+
"""Describes a basic requests authentication."""
60+
61+
def __init__(self, username: str, password: str):
62+
requests.auth.HTTPBasicAuth.__init__(self, username, password)
63+
64+
65+
class NTLM(requests.auth.AuthBase, SupportMultiAuth):
66+
"""Describes a NTLM requests authentication."""
67+
68+
def __init__(self, username: str = None, password: str = None):
69+
"""
70+
:param username: Mandatory if requests_negotiate_sspi module is not installed.
71+
:param password: Mandatory if requests_negotiate_sspi module is not installed.
72+
"""
73+
self.username = username
74+
self.password = password
75+
if not username and not password:
76+
try:
77+
import requests_negotiate_sspi
78+
79+
self.auth = requests_negotiate_sspi.HttpNegotiateAuth()
80+
except ImportError:
81+
raise Exception(
82+
"NTLM authentication requires requests_negotiate_sspi module."
83+
)
84+
else:
85+
if not username:
86+
raise Exception(
87+
'NTLM authentication requires "username" to be provided in security_details.'
88+
)
89+
if not password:
90+
raise Exception(
91+
'NTLM authentication requires "password" to be provided in security_details.'
92+
)
93+
try:
94+
import requests_ntlm
95+
96+
self.auth = requests_ntlm.HttpNtlmAuth(username, password)
97+
except ImportError:
98+
raise Exception("NTLM authentication requires requests_ntlm module.")
99+
100+
def __call__(self, r):
101+
self.auth.__call__(r)
102+
return r
103+
104+
105+
class _MultiAuth(requests.auth.AuthBase):
106+
"""Authentication using multiple authentication methods."""
107+
108+
def __init__(self, *authentication_modes):
109+
self.authentication_modes = authentication_modes
110+
111+
def __call__(self, r):
112+
for authentication_mode in self.authentication_modes:
113+
authentication_mode.__call__(r)
114+
return r
115+
116+
def __add__(self, other):
117+
if isinstance(other, _MultiAuth):
118+
return _MultiAuth(*self.authentication_modes, *other.authentication_modes)
119+
return _MultiAuth(*self.authentication_modes, other)
120+
121+
def __and__(self, other):
122+
if isinstance(other, _MultiAuth):
123+
return _MultiAuth(*self.authentication_modes, *other.authentication_modes)
124+
return _MultiAuth(*self.authentication_modes, other)
125+
126+
127+
class Auths(_MultiAuth):
128+
def __init__(self, *authentication_modes):
129+
warnings.warn(
130+
"Auths class will be removed in the future. Use + instead.",
131+
DeprecationWarning,
132+
)
133+
super().__init__(*authentication_modes)
134+
135+
136+
def _add_parameters(initial_url: str, extra_parameters: dict) -> str:
137+
"""
138+
Add parameters to an URL and return the new URL.
139+
140+
:param initial_url:
141+
:param extra_parameters: dictionary of parameters name and value.
142+
:return: the new URL containing parameters.
143+
"""
144+
scheme, netloc, path, query_string, fragment = urlsplit(initial_url)
145+
query_params = parse_qs(query_string)
146+
query_params.update(
147+
{
148+
parameter_name: [parameter_value]
149+
for parameter_name, parameter_value in extra_parameters.items()
150+
}
151+
)
152+
153+
new_query_string = urlencode(query_params, doseq=True)
154+
155+
return urlunsplit((scheme, netloc, path, new_query_string, fragment))
File renamed without changes.

requests_auth/_oauth2/__init__.py

Whitespace-only changes.

requests_auth/oauth2_authentication_responses_server.py renamed to requests_auth/_oauth2/authentication_responses_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from urllib.parse import parse_qs, urlparse
66
from socket import socket
77

8-
from requests_auth.errors import *
8+
from requests_auth._errors import *
99

1010
logger = logging.getLogger(__name__)
1111

0 commit comments

Comments
 (0)