Skip to content

Commit 4d42064

Browse files
committed
Merge branch 'feature/type-hints' into develop
2 parents 75a1e7b + 339166b commit 4d42064

File tree

12 files changed

+253
-155
lines changed

12 files changed

+253
-155
lines changed

MANIFEST.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ include LICENSE.txt
22
include DESCRIPTION.rst
33
include README.rst
44
include .pylintrc
5+
include aiosfstream/py.typed
56
graft tests
67
graft docs
78
global-exclude *.pyc
9+
global-exclude .python-version
810
prune docs/build
11+
prune venv*

aiosfstream/auth.py

Lines changed: 55 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
from http import HTTPStatus
44
import reprlib
55
import json
6+
from typing import Optional, Tuple
67

78
from aiocometd import AuthExtension
9+
from aiocometd.typing import JsonObject, JsonLoader, JsonDumper, Payload, \
10+
Headers
811
from aiohttp import ClientSession
912
from aiohttp.client_exceptions import ClientError
1013

@@ -20,55 +23,70 @@
2023
class AuthenticatorBase(AuthExtension):
2124
"""Abstract base class to serve as a base for implementing concrete
2225
authenticators"""
23-
def __init__(self, sandbox=False, json_dumps=json.dumps,
24-
json_loads=json.loads):
26+
def __init__(self, sandbox: bool = False,
27+
json_dumps: JsonDumper = json.dumps,
28+
json_loads: JsonLoader = json.loads) -> None:
2529
"""
26-
:param bool sandbox: Marks whether the authentication has to be done \
30+
:param sandbox: Marks whether the authentication has to be done \
2731
for a sandbox org or for a production org
2832
:param json_dumps: Function for JSON serialization, the default is \
2933
:func:`json.dumps`
30-
:type json_dumps: :func:`callable`
3134
:param json_loads: Function for JSON deserialization, the default is \
3235
:func:`json.loads`
33-
:type json_loads: :func:`callable`
3436
"""
3537
#: Marks whether the authentication has to be done for a sandbox org \
3638
#: or for a production org
3739
self._sandbox = sandbox
3840
#: Salesforce session ID that can be used with the web services API
39-
self.access_token = None
41+
self.access_token: Optional[str] = None
4042
#: Value is Bearer for all responses that include an access token
41-
self.token_type = None
43+
self.token_type: Optional[str] = None
4244
#: A URL indicating the instance of the user’s org
43-
self.instance_url = None
45+
self.instance_url: Optional[str] = None
4446
#: Identity URL that can be used to both identify the user and query \
4547
#: for more information about the user
46-
self.id = None # pylint: disable=invalid-name
48+
self.id: Optional[str] = None # pylint: disable=invalid-name
4749
#: Base64-encoded HMAC-SHA256 signature signed with the consumer’s \
4850
#: private key containing the concatenated ID and issued_at. Use to \
4951
#: verify that the identity URL hasn’t changed since the server sent it
50-
self.signature = None
52+
self.signature: Optional[str] = None
5153
#: Timestamp when the signature was created
52-
self.issued_at = None
54+
self.issued_at: Optional[str] = None
5355
#: Function for JSON serialization
5456
self.json_dumps = json_dumps
5557
#: Function for JSON deserialization
5658
self.json_loads = json_loads
5759

5860
@property
59-
def _token_url(self):
61+
def _token_url(self) -> str:
6062
"""The URL that should be used for token requests"""
6163
if self._sandbox:
6264
return SANDBOX_TOKEN_URL
6365
return TOKEN_URL
6466

65-
async def outgoing(self, payload, headers):
67+
async def outgoing(self, payload: Payload, headers: Headers) -> None:
68+
"""Process outgoing *payload* and *headers*
69+
70+
Called just before a payload is sent to insert the ``Authorization`` \
71+
header value.
72+
73+
:param payload: List of outgoing messages
74+
:param headers: Headers to send
75+
:raise AuthenticationError: If the value of :py:attr:`~token_type` or \
76+
:py:attr:`~access_token` is ``None``. In other words, it's raised if \
77+
the method is called without authenticating first.
78+
"""
79+
if self.token_type is None or self.access_token is None:
80+
raise AuthenticationError("Unknown token_type and access_token "
81+
"values. Method called without "
82+
"authenticating first.")
6683
headers["Authorization"] = self.token_type + " " + self.access_token
6784

68-
async def incoming(self, payload, headers=None):
85+
async def incoming(self, payload: Payload,
86+
headers: Optional[Headers] = None) -> None:
6987
pass
7088

71-
async def authenticate(self):
89+
async def authenticate(self) -> None:
7290
"""Called on initialization and after a failed authentication attempt
7391
7492
:raise AuthenticationError: If the server rejects the authentication \
@@ -91,11 +109,10 @@ async def authenticate(self):
91109
self.__dict__.update(response_data)
92110

93111
@abstractmethod
94-
async def _authenticate(self):
112+
async def _authenticate(self) -> Tuple[int, JsonObject]:
95113
"""Authenticate the user
96114
97115
:return: The status code and response data from the server's response
98-
:rtype: tuple(int, dict)
99116
:raise aiohttp.client_exceptions.ClientError: If a network failure \
100117
occurs
101118
"""
@@ -106,23 +123,23 @@ async def _authenticate(self):
106123

107124
class PasswordAuthenticator(AuthenticatorBase):
108125
"""Authenticator for using the OAuth 2.0 Username-Password Flow"""
109-
def __init__(self, consumer_key, consumer_secret, username, password,
110-
sandbox=False, json_dumps=json.dumps, json_loads=json.loads):
126+
def __init__(self, consumer_key: str, consumer_secret: str,
127+
username: str, password: str, sandbox: bool = False,
128+
json_dumps: JsonDumper = json.dumps,
129+
json_loads: JsonLoader = json.loads) -> None:
111130
"""
112-
:param str consumer_key: Consumer key from the Salesforce connected \
131+
:param consumer_key: Consumer key from the Salesforce connected \
113132
app definition
114-
:param str consumer_secret: Consumer secret from the Salesforce \
133+
:param consumer_secret: Consumer secret from the Salesforce \
115134
connected app definition
116-
:param str username: Salesforce username
117-
:param str password: Salesforce password
118-
:param bool sandbox: Marks whether the authentication has to be done \
135+
:param username: Salesforce username
136+
:param password: Salesforce password
137+
:param sandbox: Marks whether the authentication has to be done \
119138
for a sandbox org or for a production org
120139
:param json_dumps: Function for JSON serialization, the default is \
121140
:func:`json.dumps`
122-
:type json_dumps: :func:`callable`
123141
:param json_loads: Function for JSON deserialization, the default is \
124142
:func:`json.loads`
125-
:type json_loads: :func:`callable`
126143
"""
127144
super().__init__(sandbox=sandbox,
128145
json_dumps=json_dumps,
@@ -136,15 +153,15 @@ def __init__(self, consumer_key, consumer_secret, username, password,
136153
#: Salesforce password
137154
self.password = password
138155

139-
def __repr__(self):
156+
def __repr__(self) -> str:
140157
"""Formal string representation"""
141158
cls_name = type(self).__name__
142159
return f"{cls_name}(consumer_key={reprlib.repr(self.client_id)}," \
143160
f"consumer_secret={reprlib.repr(self.client_secret)}, " \
144161
f"username={reprlib.repr(self.username)}, " \
145162
f"password={reprlib.repr(self.password)})"
146163

147-
async def _authenticate(self):
164+
async def _authenticate(self) -> Tuple[int, JsonObject]:
148165
async with ClientSession(json_serialize=self.json_dumps) as session:
149166
data = {
150167
"grant_type": "password",
@@ -160,24 +177,24 @@ async def _authenticate(self):
160177

161178
class RefreshTokenAuthenticator(AuthenticatorBase):
162179
"""Authenticator for using the OAuth 2.0 Refresh Token Flow"""
163-
def __init__(self, consumer_key, consumer_secret, refresh_token,
164-
sandbox=False, json_dumps=json.dumps, json_loads=json.loads):
180+
def __init__(self, consumer_key: str, consumer_secret: str,
181+
refresh_token: str, sandbox: bool = False,
182+
json_dumps: JsonDumper = json.dumps,
183+
json_loads: JsonLoader = json.loads) -> None:
165184
"""
166-
:param str consumer_key: Consumer key from the Salesforce connected \
185+
:param consumer_key: Consumer key from the Salesforce connected \
167186
app definition
168-
:param str consumer_secret: Consumer secret from the Salesforce \
187+
:param consumer_secret: Consumer secret from the Salesforce \
169188
connected app definition
170-
:param str refresh_token: A refresh token obtained from Salesforce \
189+
:param refresh_token: A refresh token obtained from Salesforce \
171190
by using one of its authentication methods (for example with the \
172191
OAuth 2.0 Web Server Authentication Flow)
173-
:param bool sandbox: Marks whether the authentication has to be done \
192+
:param sandbox: Marks whether the authentication has to be done \
174193
for a sandbox org or for a production org
175194
:param json_dumps: Function for JSON serialization, the default is \
176195
:func:`json.dumps`
177-
:type json_dumps: :func:`callable`
178196
:param json_loads: Function for JSON deserialization, the default is \
179197
:func:`json.loads`
180-
:type json_loads: :func:`callable`
181198
"""
182199
super().__init__(sandbox=sandbox,
183200
json_dumps=json_dumps,
@@ -189,14 +206,14 @@ def __init__(self, consumer_key, consumer_secret, refresh_token,
189206
#: Salesforce refresh token
190207
self.refresh_token = refresh_token
191208

192-
def __repr__(self):
209+
def __repr__(self) -> str:
193210
"""Formal string representation"""
194211
cls_name = type(self).__name__
195212
return f"{cls_name}(consumer_key={reprlib.repr(self.client_id)}," \
196213
f"consumer_secret={reprlib.repr(self.client_secret)}, " \
197214
f"refresh_token={reprlib.repr(self.refresh_token)})"
198215

199-
async def _authenticate(self):
216+
async def _authenticate(self) -> Tuple[int, JsonObject]:
200217
async with ClientSession(json_serialize=self.json_dumps) as session:
201218
data = {
202219
"grant_type": "refresh_token",

0 commit comments

Comments
 (0)