PyHiveLMS 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyhive/__init__.py +13 -0
- pyhive/cli/__init__.py +0 -0
- pyhive/cli/main.py +30 -0
- pyhive/client.py +570 -0
- pyhive/src/__init__.py +0 -0
- pyhive/src/_generated_versions.py +3 -0
- pyhive/src/api_versions.py +6 -0
- pyhive/src/authenticated_hive_client.py +250 -0
- pyhive/src/types/__init__.py +0 -0
- pyhive/src/types/assignment.py +210 -0
- pyhive/src/types/assignment_response.py +205 -0
- pyhive/src/types/assignment_response_content.py +131 -0
- pyhive/src/types/autocheck_status.py +94 -0
- pyhive/src/types/class_.py +113 -0
- pyhive/src/types/common.py +56 -0
- pyhive/src/types/core_item.py +22 -0
- pyhive/src/types/enums/__init__.py +0 -0
- pyhive/src/types/enums/action_enum.py +18 -0
- pyhive/src/types/enums/assignment_response_type_enum.py +17 -0
- pyhive/src/types/enums/assignment_status_enum.py +17 -0
- pyhive/src/types/enums/class_type_enum.py +13 -0
- pyhive/src/types/enums/clearance_enum.py +16 -0
- pyhive/src/types/enums/event_type_enum.py +14 -0
- pyhive/src/types/enums/exercise_patbas_enum.py +15 -0
- pyhive/src/types/enums/exercise_preview_types.py +15 -0
- pyhive/src/types/enums/form_field_type_enum.py +15 -0
- pyhive/src/types/enums/gender_enum.py +14 -0
- pyhive/src/types/enums/help_response_type_enum.py +14 -0
- pyhive/src/types/enums/help_status_enum.py +13 -0
- pyhive/src/types/enums/help_type_enum.py +18 -0
- pyhive/src/types/enums/queue_rule_enum.py +15 -0
- pyhive/src/types/enums/status_enum.py +21 -0
- pyhive/src/types/enums/sync_status_enum.py +15 -0
- pyhive/src/types/enums/visibility_enum.py +14 -0
- pyhive/src/types/event.py +140 -0
- pyhive/src/types/event_attendees_type_0_item.py +69 -0
- pyhive/src/types/event_color.py +63 -0
- pyhive/src/types/exercise.py +216 -0
- pyhive/src/types/form_field.py +152 -0
- pyhive/src/types/help_.py +275 -0
- pyhive/src/types/help_response.py +113 -0
- pyhive/src/types/help_response_segel_nested.py +129 -0
- pyhive/src/types/module.py +141 -0
- pyhive/src/types/notification_nested.py +80 -0
- pyhive/src/types/program.py +180 -0
- pyhive/src/types/queue.py +150 -0
- pyhive/src/types/queue_item.py +88 -0
- pyhive/src/types/subject.py +156 -0
- pyhive/src/types/tag.py +62 -0
- pyhive/src/types/user.py +450 -0
- pyhive/types.py +23 -0
- pyhivelms-1.0.0.dist-info/METADATA +156 -0
- pyhivelms-1.0.0.dist-info/RECORD +55 -0
- pyhivelms-1.0.0.dist-info/WHEEL +4 -0
- pyhivelms-1.0.0.dist-info/entry_points.txt +2 -0
pyhive/src/types/tag.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Module defining the Tag class for Hive tags."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar
|
|
5
|
+
|
|
6
|
+
from attrs import define
|
|
7
|
+
from .core_item import HiveCoreItem
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from ...client import HiveClient
|
|
11
|
+
|
|
12
|
+
T = TypeVar("T", bound="Tag")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@define
|
|
16
|
+
class Tag(HiveCoreItem):
|
|
17
|
+
"""Attributes:
|
|
18
|
+
id (int):
|
|
19
|
+
name (str):
|
|
20
|
+
color (str):
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
hive_client: "HiveClient"
|
|
25
|
+
id: int
|
|
26
|
+
name: str
|
|
27
|
+
color: str
|
|
28
|
+
|
|
29
|
+
def to_dict(self) -> dict[str, Any]:
|
|
30
|
+
id = self.id
|
|
31
|
+
|
|
32
|
+
name = self.name
|
|
33
|
+
|
|
34
|
+
color = self.color
|
|
35
|
+
|
|
36
|
+
field_dict: dict[str, Any] = {}
|
|
37
|
+
field_dict.update(
|
|
38
|
+
{
|
|
39
|
+
"id": id,
|
|
40
|
+
"name": name,
|
|
41
|
+
"color": color,
|
|
42
|
+
},
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
return field_dict
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def from_dict(cls, src_dict: Mapping[str, Any], hive_client: "HiveClient") -> Self:
|
|
49
|
+
d = dict(src_dict)
|
|
50
|
+
id = d.pop("id")
|
|
51
|
+
|
|
52
|
+
name = d.pop("name")
|
|
53
|
+
|
|
54
|
+
color = d.pop("color")
|
|
55
|
+
|
|
56
|
+
tag = cls(
|
|
57
|
+
id=id,
|
|
58
|
+
name=name,
|
|
59
|
+
color=color,
|
|
60
|
+
hive_client=hive_client,
|
|
61
|
+
)
|
|
62
|
+
return tag
|
pyhive/src/types/user.py
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
"""Hive management course user type."""
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
from collections.abc import Mapping
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast, Generator
|
|
6
|
+
|
|
7
|
+
from attrs import field, define
|
|
8
|
+
from dateutil.parser import isoparse
|
|
9
|
+
from .common import UNSET, Unset
|
|
10
|
+
from .core_item import HiveCoreItem
|
|
11
|
+
from .enums.clearance_enum import ClearanceEnum
|
|
12
|
+
from .enums.gender_enum import GenderEnum
|
|
13
|
+
from .enums.status_enum import StatusEnum
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from ...client import HiveClient
|
|
17
|
+
from .assignment import Assignment
|
|
18
|
+
from .class_ import Class
|
|
19
|
+
from .program import Program
|
|
20
|
+
from .queue import Queue
|
|
21
|
+
|
|
22
|
+
T = TypeVar("T", bound="User")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@define
|
|
26
|
+
class User(HiveCoreItem): # pylint: disable=too-many-instance-attributes
|
|
27
|
+
"""Hive management course user.
|
|
28
|
+
|
|
29
|
+
Attributes:
|
|
30
|
+
id (int):
|
|
31
|
+
display_name (str):
|
|
32
|
+
clearance (ClearanceEnum):
|
|
33
|
+
* `1` - Hanich
|
|
34
|
+
* `2` - Checker
|
|
35
|
+
* `3` - Segel
|
|
36
|
+
* `5` - Admin
|
|
37
|
+
gender (GenderEnum):
|
|
38
|
+
* `Male` - Male
|
|
39
|
+
* `Female` - Female
|
|
40
|
+
* `NonBinary` - Nonbinary
|
|
41
|
+
current_assignment (Union[None, int]):
|
|
42
|
+
current_assignment_options (list[int]):
|
|
43
|
+
mentee_ids (list[int]):
|
|
44
|
+
username (str): Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.
|
|
45
|
+
status (StatusEnum):
|
|
46
|
+
* `Present` - Present
|
|
47
|
+
* `Raised Hand` - Raisedhand
|
|
48
|
+
* `Toilet Request` - Toiletrequest
|
|
49
|
+
* `Toilet` - Toilet
|
|
50
|
+
* `Personal Talk` - Personaltalk
|
|
51
|
+
* `Work Talk` - Worktalk
|
|
52
|
+
* `Medical` - Medical
|
|
53
|
+
* `Prayer` - Prayer
|
|
54
|
+
* `Room` - Room
|
|
55
|
+
* `Home` - Home
|
|
56
|
+
status_date (datetime.datetime):
|
|
57
|
+
avatar_filename (Union[Unset, str]):
|
|
58
|
+
number (Union[None, Unset, int]):
|
|
59
|
+
program (Union[None, Unset, int]):
|
|
60
|
+
checkers_brief (Union[Unset, str]):
|
|
61
|
+
mentor (Union[None, Unset, int]):
|
|
62
|
+
classes (Union[Unset, list[int]]):
|
|
63
|
+
first_name (Union[Unset, str]):
|
|
64
|
+
last_name (Union[Unset, str]):
|
|
65
|
+
queue (Union[None, Unset, int]):
|
|
66
|
+
disable_queue (Union[Unset, bool]):
|
|
67
|
+
user_queue (Union[None, Unset, int]):
|
|
68
|
+
disable_user_queue (Union[Unset, bool]):
|
|
69
|
+
override_queue (Union[None, Unset, int]):
|
|
70
|
+
confirmed (Union[Unset, bool]):
|
|
71
|
+
teacher (Union[Unset, bool]):
|
|
72
|
+
hostname (Union[Unset, str]):
|
|
73
|
+
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
hive_client: "HiveClient"
|
|
77
|
+
id: int
|
|
78
|
+
display_name: str
|
|
79
|
+
clearance: ClearanceEnum
|
|
80
|
+
gender: GenderEnum
|
|
81
|
+
current_assignment_id: None | int
|
|
82
|
+
_current_assignment: "Assignment | None" = field(init=False, default=None)
|
|
83
|
+
current_assignment_options: list[int]
|
|
84
|
+
mentee_ids: list[int]
|
|
85
|
+
_mentees: "list[User] | None" = field(init=False, default=None)
|
|
86
|
+
username: str
|
|
87
|
+
status: StatusEnum
|
|
88
|
+
status_date: datetime.datetime
|
|
89
|
+
avatar_filename: Unset | str = UNSET
|
|
90
|
+
number: None | Unset | int = UNSET
|
|
91
|
+
program_id: None | Unset | int = UNSET
|
|
92
|
+
_program: "Program | None" = field(init=False, default=None)
|
|
93
|
+
checkers_brief: Unset | str = UNSET
|
|
94
|
+
mentor_id: None | Unset | int = UNSET
|
|
95
|
+
_mentor: "User | None" = field(init=False, default=None)
|
|
96
|
+
class_ids: Unset | list[int] = UNSET
|
|
97
|
+
_classes: "list[Class] | None" = field(init=False, default=None)
|
|
98
|
+
first_name: Unset | str = UNSET
|
|
99
|
+
last_name: Unset | str = UNSET
|
|
100
|
+
queue_id: None | Unset | int = UNSET
|
|
101
|
+
_queue: "Queue | None" = field(init=False, default=None)
|
|
102
|
+
disable_queue: Unset | bool = UNSET
|
|
103
|
+
user_queue_id: None | Unset | int = UNSET
|
|
104
|
+
_user_queue: "Queue | None" = field(init=False, default=None)
|
|
105
|
+
disable_user_queue: Unset | bool = UNSET
|
|
106
|
+
override_queue_id: None | Unset | int = UNSET
|
|
107
|
+
_override_queue: "Queue | None" = field(init=False, default=None)
|
|
108
|
+
confirmed: Unset | bool = UNSET
|
|
109
|
+
teacher: Unset | bool = UNSET
|
|
110
|
+
hostname: Unset | str = UNSET
|
|
111
|
+
|
|
112
|
+
def to_dict( # pylint: disable=too-many-locals, too-many-statements, too-many-branches
|
|
113
|
+
self,
|
|
114
|
+
) -> dict[str, Any]:
|
|
115
|
+
id = self.id
|
|
116
|
+
|
|
117
|
+
display_name = self.display_name
|
|
118
|
+
|
|
119
|
+
clearance = self.clearance.value
|
|
120
|
+
|
|
121
|
+
gender = self.gender.value
|
|
122
|
+
|
|
123
|
+
current_assignment_id: None | int
|
|
124
|
+
current_assignment_id = self.current_assignment_id
|
|
125
|
+
|
|
126
|
+
current_assignment_options = self.current_assignment_options
|
|
127
|
+
|
|
128
|
+
mentee_ids = self.mentee_ids
|
|
129
|
+
|
|
130
|
+
username = self.username
|
|
131
|
+
|
|
132
|
+
status = self.status.value
|
|
133
|
+
|
|
134
|
+
status_date = self.status_date.isoformat()
|
|
135
|
+
|
|
136
|
+
avatar_filename = self.avatar_filename
|
|
137
|
+
|
|
138
|
+
number: None | Unset | int
|
|
139
|
+
number = UNSET if isinstance(self.number, Unset) else self.number
|
|
140
|
+
|
|
141
|
+
program_id: None | Unset | int
|
|
142
|
+
program_id = UNSET if isinstance(self.program_id, Unset) else self.program_id
|
|
143
|
+
|
|
144
|
+
checkers_brief = self.checkers_brief
|
|
145
|
+
|
|
146
|
+
mentor_id: None | Unset | int
|
|
147
|
+
mentor_id = UNSET if isinstance(self.mentor_id, Unset) else self.mentor_id
|
|
148
|
+
|
|
149
|
+
class_ids: Unset | list[int] = UNSET
|
|
150
|
+
if not isinstance(self.class_ids, Unset):
|
|
151
|
+
class_ids = self.class_ids
|
|
152
|
+
|
|
153
|
+
first_name = self.first_name
|
|
154
|
+
|
|
155
|
+
last_name = self.last_name
|
|
156
|
+
|
|
157
|
+
queue_id: None | Unset | int
|
|
158
|
+
queue_id = UNSET if isinstance(self.queue_id, Unset) else self.queue_id
|
|
159
|
+
|
|
160
|
+
disable_queue = self.disable_queue
|
|
161
|
+
|
|
162
|
+
user_queue_id: None | Unset | int
|
|
163
|
+
user_queue_id = (
|
|
164
|
+
UNSET if isinstance(self.user_queue_id, Unset) else self.user_queue_id
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
disable_user_queue = self.disable_user_queue
|
|
168
|
+
|
|
169
|
+
override_queue_id: None | Unset | int
|
|
170
|
+
override_queue_id = (
|
|
171
|
+
UNSET
|
|
172
|
+
if isinstance(self.override_queue_id, Unset)
|
|
173
|
+
else self.override_queue_id
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
confirmed = self.confirmed
|
|
177
|
+
|
|
178
|
+
teacher = self.teacher
|
|
179
|
+
|
|
180
|
+
hostname = self.hostname
|
|
181
|
+
|
|
182
|
+
field_dict: dict[str, Any] = {}
|
|
183
|
+
field_dict.update(
|
|
184
|
+
{
|
|
185
|
+
"id": id,
|
|
186
|
+
"display_name": display_name,
|
|
187
|
+
"clearance": clearance,
|
|
188
|
+
"gender": gender,
|
|
189
|
+
"current_assignment": current_assignment_id,
|
|
190
|
+
"current_assignment_options": current_assignment_options,
|
|
191
|
+
"mentees": mentee_ids,
|
|
192
|
+
"username": username,
|
|
193
|
+
"status": status,
|
|
194
|
+
"status_date": status_date,
|
|
195
|
+
},
|
|
196
|
+
)
|
|
197
|
+
if avatar_filename is not UNSET:
|
|
198
|
+
field_dict["avatar_filename"] = avatar_filename
|
|
199
|
+
if number is not UNSET:
|
|
200
|
+
field_dict["number"] = number
|
|
201
|
+
if program_id is not UNSET:
|
|
202
|
+
field_dict["program"] = program_id
|
|
203
|
+
if checkers_brief is not UNSET:
|
|
204
|
+
field_dict["checkers_brief"] = checkers_brief
|
|
205
|
+
if mentor_id is not UNSET:
|
|
206
|
+
field_dict["mentor"] = mentor_id
|
|
207
|
+
if class_ids is not UNSET:
|
|
208
|
+
field_dict["classes"] = class_ids
|
|
209
|
+
if first_name is not UNSET:
|
|
210
|
+
field_dict["first_name"] = first_name
|
|
211
|
+
if last_name is not UNSET:
|
|
212
|
+
field_dict["last_name"] = last_name
|
|
213
|
+
if queue_id is not UNSET:
|
|
214
|
+
field_dict["queue"] = queue_id
|
|
215
|
+
if disable_queue is not UNSET:
|
|
216
|
+
field_dict["disable_queue"] = disable_queue
|
|
217
|
+
if user_queue_id is not UNSET:
|
|
218
|
+
field_dict["user_queue"] = user_queue_id
|
|
219
|
+
if disable_user_queue is not UNSET:
|
|
220
|
+
field_dict["disable_user_queue"] = disable_user_queue
|
|
221
|
+
if override_queue_id is not UNSET:
|
|
222
|
+
field_dict["override_queue"] = override_queue_id
|
|
223
|
+
if confirmed is not UNSET:
|
|
224
|
+
field_dict["confirmed"] = confirmed
|
|
225
|
+
if teacher is not UNSET:
|
|
226
|
+
field_dict["teacher"] = teacher
|
|
227
|
+
if hostname is not UNSET:
|
|
228
|
+
field_dict["hostname"] = hostname
|
|
229
|
+
|
|
230
|
+
return field_dict
|
|
231
|
+
|
|
232
|
+
@classmethod
|
|
233
|
+
def from_dict( # pylint: disable=too-many-locals
|
|
234
|
+
cls,
|
|
235
|
+
src_dict: Mapping[str, Any],
|
|
236
|
+
hive_client: "HiveClient",
|
|
237
|
+
) -> Self:
|
|
238
|
+
"""Deserialize a User instance from a mapping."""
|
|
239
|
+
d = dict(src_dict)
|
|
240
|
+
id = d.pop("id")
|
|
241
|
+
|
|
242
|
+
display_name = d.pop("display_name")
|
|
243
|
+
|
|
244
|
+
clearance = ClearanceEnum(d.pop("clearance"))
|
|
245
|
+
|
|
246
|
+
gender = GenderEnum(d.pop("gender"))
|
|
247
|
+
|
|
248
|
+
def _parse_current_assignment(data: object) -> None | int:
|
|
249
|
+
if data is None:
|
|
250
|
+
return data
|
|
251
|
+
return cast("None | int", data)
|
|
252
|
+
|
|
253
|
+
current_assignment = _parse_current_assignment(d.pop("current_assignment"))
|
|
254
|
+
|
|
255
|
+
current_assignment_options = cast(
|
|
256
|
+
"list[int]", d.pop("current_assignment_options")
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
mentee_ids = cast("list[int]", d.pop("mentees"))
|
|
260
|
+
|
|
261
|
+
username = d.pop("username")
|
|
262
|
+
|
|
263
|
+
status = StatusEnum(d.pop("status"))
|
|
264
|
+
|
|
265
|
+
status_date = isoparse(d.pop("status_date"))
|
|
266
|
+
|
|
267
|
+
avatar_filename = d.pop("avatar_filename", UNSET)
|
|
268
|
+
|
|
269
|
+
def _parse_number(data: object) -> None | Unset | int:
|
|
270
|
+
if data is None:
|
|
271
|
+
return data
|
|
272
|
+
if isinstance(data, Unset):
|
|
273
|
+
return data
|
|
274
|
+
return cast("None | Unset | int", data)
|
|
275
|
+
|
|
276
|
+
number = _parse_number(d.pop("number", UNSET))
|
|
277
|
+
|
|
278
|
+
def _parse_program(data: object) -> None | Unset | int:
|
|
279
|
+
if data is None:
|
|
280
|
+
return data
|
|
281
|
+
if isinstance(data, Unset):
|
|
282
|
+
return data
|
|
283
|
+
return cast("None | Unset | int", data)
|
|
284
|
+
|
|
285
|
+
program = _parse_program(d.pop("program", UNSET))
|
|
286
|
+
|
|
287
|
+
checkers_brief = d.pop("checkers_brief", UNSET)
|
|
288
|
+
|
|
289
|
+
def _parse_mentor(data: object) -> None | Unset | int:
|
|
290
|
+
if data is None:
|
|
291
|
+
return data
|
|
292
|
+
if isinstance(data, Unset):
|
|
293
|
+
return data
|
|
294
|
+
return cast("None | Unset | int", data)
|
|
295
|
+
|
|
296
|
+
mentor = _parse_mentor(d.pop("mentor", UNSET))
|
|
297
|
+
|
|
298
|
+
classes = cast("list[int]", d.pop("classes", UNSET))
|
|
299
|
+
|
|
300
|
+
first_name = d.pop("first_name", UNSET)
|
|
301
|
+
|
|
302
|
+
last_name = d.pop("last_name", UNSET)
|
|
303
|
+
|
|
304
|
+
def _parse_queue(data: object) -> None | Unset | int:
|
|
305
|
+
if data is None:
|
|
306
|
+
return data
|
|
307
|
+
if isinstance(data, Unset):
|
|
308
|
+
return data
|
|
309
|
+
return cast("None | Unset | int", data)
|
|
310
|
+
|
|
311
|
+
queue = _parse_queue(d.pop("queue", UNSET))
|
|
312
|
+
|
|
313
|
+
disable_queue = d.pop("disable_queue", UNSET)
|
|
314
|
+
|
|
315
|
+
def _parse_user_queue(data: object) -> None | Unset | int:
|
|
316
|
+
if data is None:
|
|
317
|
+
return data
|
|
318
|
+
if isinstance(data, Unset):
|
|
319
|
+
return data
|
|
320
|
+
return cast("None | Unset | int", data)
|
|
321
|
+
|
|
322
|
+
user_queue = _parse_user_queue(d.pop("user_queue", UNSET))
|
|
323
|
+
|
|
324
|
+
disable_user_queue = d.pop("disable_user_queue", UNSET)
|
|
325
|
+
|
|
326
|
+
def _parse_override_queue(data: object) -> None | Unset | int:
|
|
327
|
+
if data is None:
|
|
328
|
+
return data
|
|
329
|
+
if isinstance(data, Unset):
|
|
330
|
+
return data
|
|
331
|
+
return cast("None | Unset | int", data)
|
|
332
|
+
|
|
333
|
+
override_queue = _parse_override_queue(d.pop("override_queue", UNSET))
|
|
334
|
+
|
|
335
|
+
confirmed = d.pop("confirmed", UNSET)
|
|
336
|
+
|
|
337
|
+
teacher = d.pop("teacher", UNSET)
|
|
338
|
+
|
|
339
|
+
hostname = d.pop("hostname", UNSET)
|
|
340
|
+
|
|
341
|
+
return cls(
|
|
342
|
+
id=id,
|
|
343
|
+
display_name=display_name,
|
|
344
|
+
clearance=clearance,
|
|
345
|
+
gender=gender,
|
|
346
|
+
current_assignment_id=current_assignment,
|
|
347
|
+
current_assignment_options=current_assignment_options,
|
|
348
|
+
mentee_ids=mentee_ids,
|
|
349
|
+
username=username,
|
|
350
|
+
status=status,
|
|
351
|
+
status_date=status_date,
|
|
352
|
+
avatar_filename=avatar_filename,
|
|
353
|
+
number=number,
|
|
354
|
+
program_id=program,
|
|
355
|
+
checkers_brief=checkers_brief,
|
|
356
|
+
mentor_id=mentor,
|
|
357
|
+
class_ids=classes,
|
|
358
|
+
first_name=first_name,
|
|
359
|
+
last_name=last_name,
|
|
360
|
+
queue_id=queue,
|
|
361
|
+
disable_queue=disable_queue,
|
|
362
|
+
user_queue_id=user_queue,
|
|
363
|
+
disable_user_queue=disable_user_queue,
|
|
364
|
+
override_queue_id=override_queue,
|
|
365
|
+
confirmed=confirmed,
|
|
366
|
+
teacher=teacher,
|
|
367
|
+
hostname=hostname,
|
|
368
|
+
hive_client=hive_client,
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
@property
|
|
372
|
+
def program(self) -> "Program | None":
|
|
373
|
+
"""The program this user is in."""
|
|
374
|
+
if not isinstance(self.program_id, int):
|
|
375
|
+
return None
|
|
376
|
+
if self._program is None:
|
|
377
|
+
self._program = self.hive_client.get_program(self.program_id)
|
|
378
|
+
return self._program
|
|
379
|
+
|
|
380
|
+
@property
|
|
381
|
+
def mentees(self) -> list["User"]:
|
|
382
|
+
"""The mentees of this user."""
|
|
383
|
+
if self._mentees is None:
|
|
384
|
+
self._mentees = list(
|
|
385
|
+
self.hive_client.get_users(user__id__in=self.mentee_ids)
|
|
386
|
+
)
|
|
387
|
+
return self._mentees
|
|
388
|
+
|
|
389
|
+
@property
|
|
390
|
+
def mentor(self) -> "User | None":
|
|
391
|
+
"""The mentor of this user."""
|
|
392
|
+
if not isinstance(self.mentor_id, int):
|
|
393
|
+
return None
|
|
394
|
+
if self._mentor is None:
|
|
395
|
+
self._mentor = self.hive_client.get_user(self.mentor_id)
|
|
396
|
+
return self._mentor
|
|
397
|
+
|
|
398
|
+
@property
|
|
399
|
+
def classes(self) -> list["Class"]:
|
|
400
|
+
"""The classes this user is in."""
|
|
401
|
+
if self._classes is None:
|
|
402
|
+
if isinstance(self.class_ids, Unset):
|
|
403
|
+
self._classes = []
|
|
404
|
+
else:
|
|
405
|
+
self._classes = list(
|
|
406
|
+
self.hive_client.get_classes(id__in=self.class_ids)
|
|
407
|
+
)
|
|
408
|
+
return self._classes
|
|
409
|
+
|
|
410
|
+
@property
|
|
411
|
+
def queue(self) -> "Queue | None":
|
|
412
|
+
"""The queue this user is in."""
|
|
413
|
+
if not isinstance(self.queue_id, int):
|
|
414
|
+
return None
|
|
415
|
+
if self._queue is None:
|
|
416
|
+
self._queue = self.hive_client.get_queue(self.queue_id)
|
|
417
|
+
return self._queue
|
|
418
|
+
|
|
419
|
+
@property
|
|
420
|
+
def user_queue(self) -> "Queue | None":
|
|
421
|
+
"""The user queue this user is in."""
|
|
422
|
+
if not isinstance(self.user_queue_id, int):
|
|
423
|
+
return None
|
|
424
|
+
if self._user_queue is None:
|
|
425
|
+
self._user_queue = self.hive_client.get_queue(self.user_queue_id)
|
|
426
|
+
return self._user_queue
|
|
427
|
+
|
|
428
|
+
@property
|
|
429
|
+
def override_queue(self) -> "Queue | None":
|
|
430
|
+
"""The override queue this user is in."""
|
|
431
|
+
if not isinstance(self.override_queue_id, int):
|
|
432
|
+
return None
|
|
433
|
+
if self._override_queue is None:
|
|
434
|
+
self._override_queue = self.hive_client.get_queue(self.override_queue_id)
|
|
435
|
+
return self._override_queue
|
|
436
|
+
|
|
437
|
+
@property
|
|
438
|
+
def current_assignment(self) -> "Assignment | None":
|
|
439
|
+
"""The current assignment of this user."""
|
|
440
|
+
if not isinstance(self.current_assignment_id, int):
|
|
441
|
+
return None
|
|
442
|
+
if self._current_assignment is None:
|
|
443
|
+
self._current_assignment = self.hive_client.get_assignment(
|
|
444
|
+
self.current_assignment_id
|
|
445
|
+
)
|
|
446
|
+
return self._current_assignment
|
|
447
|
+
|
|
448
|
+
def get_assignments(self) -> Generator["Assignment", None, None]:
|
|
449
|
+
"""Get all assignments for this user."""
|
|
450
|
+
return self.hive_client.get_assignments(user__id__in=[self.id])
|
pyhive/types.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Type definitions for PyHiveLMS."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
# Import the implementation from the `pyhive` package (implementation
|
|
6
|
+
# lives there) and expose the client at package level.
|
|
7
|
+
from pyhive.src.types.assignment import Assignment # re-export
|
|
8
|
+
from pyhive.src.types.assignment_response import AssignmentResponse # re-export
|
|
9
|
+
from pyhive.src.types.user import User # re-export
|
|
10
|
+
from pyhive.src.types.module import Module # re-export
|
|
11
|
+
from pyhive.src.types.exercise import Exercise # re-export
|
|
12
|
+
from pyhive.src.types.class_ import Class
|
|
13
|
+
from pyhive.src.types.form_field import FormField
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"Assignment",
|
|
17
|
+
"AssignmentResponse",
|
|
18
|
+
"User",
|
|
19
|
+
"Module",
|
|
20
|
+
"Exercise",
|
|
21
|
+
"Class",
|
|
22
|
+
"FormField",
|
|
23
|
+
]
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: PyHiveLMS
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python bindings for Hive
|
|
5
|
+
Author-email: "Michael K. Steinberg" <m.kuper.steinberg@gmail.com>
|
|
6
|
+
Requires-Python: >=3.11.0
|
|
7
|
+
Requires-Dist: attrs>=25.4.0
|
|
8
|
+
Requires-Dist: httpx
|
|
9
|
+
Requires-Dist: python-dateutil>=2.9.0
|
|
10
|
+
Requires-Dist: typer==0.20.0
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
## PyHive — a minimal Hive API client for Python
|
|
14
|
+
|
|
15
|
+
PyHive (package: `PyHiveLMS`) is a small, synchronous Python client for the Hive API. It provides:
|
|
16
|
+
|
|
17
|
+
- A simple `HiveClient` you use as a context manager to handle authentication and the HTTP session.
|
|
18
|
+
- Generator-based list endpoints for memory-efficient iteration of large result sets.
|
|
19
|
+
|
|
20
|
+
### Supported Hive Versions
|
|
21
|
+
<!-- SUPPORTED_API_VERSIONS_START -->
|
|
22
|
+
- `5.1.2`
|
|
23
|
+
- `6.2.0`
|
|
24
|
+
<!-- SUPPORTED_API_VERSIONS_END -->
|
|
25
|
+
|
|
26
|
+
## Install
|
|
27
|
+
|
|
28
|
+
Install from PyPI. It's recommended to use a virtual environment.
|
|
29
|
+
|
|
30
|
+
Using pip (PyPI):
|
|
31
|
+
|
|
32
|
+
```pwsh
|
|
33
|
+
pip install PyHiveLMS
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## Quickstart — connect and list resources
|
|
38
|
+
|
|
39
|
+
The primary entry point is `HiveClient`. It accepts your Hive username, password and the base URL for your Hive instance. Use it as a context manager to ensure the underlying HTTP session is closed cleanly.
|
|
40
|
+
|
|
41
|
+
Example — list programs and print name/ID:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from pyhive import HiveClient
|
|
45
|
+
|
|
46
|
+
USERNAME = "Mentor123"
|
|
47
|
+
PASSWORD = "Password1"
|
|
48
|
+
HIVE_URL = "https://hive.org"
|
|
49
|
+
|
|
50
|
+
with HiveClient(USERNAME, PASSWORD, HIVE_URL) as client:
|
|
51
|
+
for program in client.get_programs():
|
|
52
|
+
print(program.id, program.name)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Example — fetch a program, its subjects and modules:
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from pyhive import HiveClient
|
|
59
|
+
|
|
60
|
+
with HiveClient(USERNAME, PASSWORD, HIVE_URL) as client:
|
|
61
|
+
program = client.get_program(42)
|
|
62
|
+
print("Program:", program.name)
|
|
63
|
+
|
|
64
|
+
# list subjects for the same program
|
|
65
|
+
subjects = list(client.get_subjects(parent_program__id__in=[program.id]))
|
|
66
|
+
for subject in subjects:
|
|
67
|
+
print(" -", subject.id, subject.name)
|
|
68
|
+
|
|
69
|
+
# modules for the first subject
|
|
70
|
+
if subjects:
|
|
71
|
+
for module in client.get_modules(parent_subject=subjects[0]):
|
|
72
|
+
print(" *", module.id, module.name)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Example — find exercises in a module and read their form fields:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
with HiveClient(USERNAME, PASSWORD, HIVE_URL) as client:
|
|
79
|
+
# you can pass ids or model objects to filter helpers
|
|
80
|
+
module = client.get_module(123)
|
|
81
|
+
for exercise in client.get_exercises(parent_module=module):
|
|
82
|
+
print(exercise.id, exercise.name)
|
|
83
|
+
for field in client.get_exercise_fields(exercise):
|
|
84
|
+
print(" field:", field.id, field.label)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Example — list assignments for a user and read responses:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
with HiveClient(USERNAME, PASSWORD, HIVE_URL) as client:
|
|
91
|
+
assignments = client.get_assignments(user__id__in=[55])
|
|
92
|
+
for a in assignments:
|
|
93
|
+
print("Assignment:", a.id, a.exercise_name)
|
|
94
|
+
for resp in client.get_assignment_responses(a):
|
|
95
|
+
print(" response:", resp.id, resp.submitted_by)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Filtering and convenience
|
|
99
|
+
|
|
100
|
+
- List endpoints (`get_programs`, `get_subjects`, `get_modules`, `get_exercises`, `get_assignments`, `get_users`, etc.) accept filter keyword arguments that are forwarded to the API. Use `id__in`, `parent_program__id__in`, `queue__id`, and the other documented kwargs to restrict results.
|
|
101
|
+
- Many methods accept either an integer id or a model instance. For example `client.get_exercise_fields(exercise_id_or_model)` accepts either.
|
|
102
|
+
|
|
103
|
+
## Error handling
|
|
104
|
+
|
|
105
|
+
Network and HTTP errors are surfaced from the underlying `httpx` client. Typical patterns:
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from httpx import HTTPError
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
with HiveClient(USERNAME, PASSWORD, HIVE_URL) as client:
|
|
112
|
+
programs = list(client.get_programs())
|
|
113
|
+
except HTTPError as exc:
|
|
114
|
+
print("Network/HTTP error:", exc)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Model parsing errors will raise normal Python exceptions — wrap calls where you need robust failure handling.
|
|
118
|
+
|
|
119
|
+
## Common methods (short reference)
|
|
120
|
+
|
|
121
|
+
- HiveClient(username, password, hive_url, **kwargs) — construct and authenticate client
|
|
122
|
+
- get_programs(...)
|
|
123
|
+
- get_program(program_id)
|
|
124
|
+
- get_subjects(...)
|
|
125
|
+
- get_modules(...)
|
|
126
|
+
- get_exercises(...)
|
|
127
|
+
- get_exercise(exercise_id)
|
|
128
|
+
- get_exercise_fields(exercise)
|
|
129
|
+
- get_assignments(...)
|
|
130
|
+
- get_assignment(assignment_id)
|
|
131
|
+
- get_assignment_responses(assignment)
|
|
132
|
+
- get_users(...)
|
|
133
|
+
- get_classes(...)
|
|
134
|
+
|
|
135
|
+
Return values are typed model objects from `src/types` or generators of those objects.
|
|
136
|
+
|
|
137
|
+
## Try it locally / Run tests
|
|
138
|
+
|
|
139
|
+
Install dev dependencies and run tests with pytest:
|
|
140
|
+
|
|
141
|
+
```pwsh
|
|
142
|
+
pip install -e .
|
|
143
|
+
pytest -q
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Troubleshooting
|
|
147
|
+
|
|
148
|
+
- Authentication errors: verify username/password and the `hive_url` base. The client authenticates at construction.
|
|
149
|
+
- SSL verification: pass `verify=False` to the client constructor for self-signed servers (not recommended for production).
|
|
150
|
+
|
|
151
|
+
## Contributing & development
|
|
152
|
+
|
|
153
|
+
- Tests live under `tests/` and show common usage patterns. Use them as examples.
|
|
154
|
+
- The typed models are in `src/types` and the `HiveClient` convenience layer is in `pyhive/client.py`.
|
|
155
|
+
|
|
156
|
+
If you plan to make changes, please add tests for new behavior and keep changes small and focused.
|