-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.py
217 lines (181 loc) · 7.33 KB
/
client.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
import json
from .connection import USOSAPIConnection
from .helper import APIHelper
from .logger import get_logger
from .services import (
APIDocumentationService,
APIServerService,
CourseService,
GradeService,
GroupService,
RegistrationService,
TermService,
UserService,
)
_LOGGER = get_logger("USOSClient")
class USOSClient:
"""
A client for the USOS API.
:var UserService user_service: The user service.
:var GroupService group_service: The group service.
:var APIServerService api_server_service: The API server service.
:var APIDocumentationService api_documentation_service: The API documentation service.
:var CourseService course_service: The course service.
:var TermService term_service: The term service.
:var GradeService grade_service: The grade service.
:var RegistrationService registration_service: The registration service.
:ivar USOSAPIConnection connection: The connection to the USOS API, used for making requests.
"""
def __init__(
self,
api_base_address: str,
consumer_key: str,
consumer_secret: str,
trust_env: bool = False,
) -> None:
"""
Initialize the USOS API client.
:param api_base_address: The base address of the USOS API.
:param consumer_key: Consumer key obtained from the USOS API.
:param consumer_secret: Consumer secret obtained from the USOS API.
:param trust_env: Whether to trust the environment variables for the connection, see https://docs.aiohttp.org/en/stable/client_reference.html#aiohttp.ClientSession for more information.
"""
self.connection = USOSAPIConnection(
api_base_address, consumer_key, consumer_secret, trust_env
)
self.user_service = UserService(self.connection)
self.group_service = GroupService(self.connection)
self.course_service = CourseService(self.connection)
self.term_service = TermService(self.connection)
self.grade_service = GradeService(self.connection)
self.api_server_service = APIServerService(self.connection)
self.api_documentation_service = APIDocumentationService(self.connection)
self.registration_service = RegistrationService(self.connection)
self.helper = APIHelper(self)
async def __aenter__(self) -> "USOSClient":
"""
Enter the client.
:return: The client.
"""
await self.open()
return self
async def __aexit__(self, exc_type, exc_value, traceback):
"""
Exit the client.
:param exc_type: The exception type.
:param exc_value: The exception value.
:param traceback: The traceback.
"""
await self.close()
async def close(self) -> None:
"""
Close the client.
"""
await self.connection.close()
async def open(self) -> None:
"""
Open the client.
"""
await self.connection.open()
def set_scopes(self, scopes: list[str]) -> None:
"""
Set the scopes for the client.
:param scopes: The scopes to set.
"""
self.connection.auth_manager.SCOPES = "|".join(scopes)
def add_scope(self, scope: str) -> None:
"""
Add a scope to the client.
:param scope: The scope to add.
"""
self.connection.auth_manager.SCOPES += f"|{scope}"
def remove_scope(self, scope: str) -> None:
"""
Remove a scope from the client.
:param scope: The scope to remove.
"""
self.connection.auth_manager.SCOPES = "|".join(
[s for s in self.connection.auth_manager.SCOPES.split("|") if s != scope]
)
async def authorize(
self, verifier: str, request_token: str = None, request_token_secret: str = None
) -> tuple[str, str]:
"""
Authorize the client with verifier and optionally token and token secret.
Parameters `token` and `token_secret` can be useful when you create a new client instance and want to authorize it with the token and secret obtained from another client instance.
:param verifier: The verifier to authorize the client with.
:param request_token: The OAuth token obtained from the previous step.
:param request_token_secret: The OAuth token secret obtained from the previous step.
:return: The access token and secret.
"""
return await self.connection.auth_manager.authorize(
verifier, request_token, request_token_secret
)
async def get_authorization_url(
self, callback_url: str = "oob", confirm_user: bool = False
) -> str:
"""
Get the URL to authorize the client.
:param callback_url: The URL to redirect to after authorization, leave as "oob" for pin-based authorization.
:param confirm_user: Whether to confirm the user before authorizing the client.
:return: The URL to authorize the client.
"""
return await self.connection.auth_manager.get_authorization_url(
callback_url, confirm_user
)
def load_access_token(self, access_token: str, access_token_secret: str):
"""
Load the access token and secret into the client.
:param access_token: The access token.
:param access_token_secret: The access token secret.
"""
self.connection.auth_manager.load_access_token(
access_token, access_token_secret
)
def load_access_token_from_json(self, json_data: dict):
"""
Load the access token and secret from a JSON object.
:param json_data: The JSON object containing the access token and secret.
"""
try:
access_token = json_data["access_token"]
access_token_secret = json_data["access_token_secret"]
except KeyError:
raise ValueError("Invalid JSON data.")
self.load_access_token(access_token, access_token_secret)
async def load_access_token_from_file(
self, file_path: str = "usos_api_access_token.json"
) -> None:
"""
Load the access token and secret from a JSON file.
:param file_path: The path to the JSON file.
"""
if not file_path.endswith(".json"):
raise ValueError("File must be a JSON file.")
with open(file_path, "r") as file:
json_data = json.load(file)
self.load_access_token_from_json(json_data)
async def save_access_token_to_file(
self, file_path: str = "usos_api_access_token.json"
) -> None:
"""
Save the access token and secret to a JSON file.
:param file_path: The path to the JSON file.
"""
if not file_path.endswith(".json"):
raise ValueError("File must be a JSON file.")
access_token, access_token_secret = (
self.connection.auth_manager.get_access_token()
)
json_data = {
"access_token": access_token,
"access_token_secret": access_token_secret,
}
with open(file_path, "w") as file:
json.dump(json_data, file)
async def test_connection(self) -> bool:
"""
Test the connection to the USOS API.
:return: True if the connection is successful, False otherwise.
"""
return await self.connection.test_connection()