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
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""Model definition for a nested notification in the Hive system.
|
|
2
|
+
|
|
3
|
+
Represents a lightweight notification object, optionally referencing a user and comment.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast
|
|
8
|
+
|
|
9
|
+
from attrs import define
|
|
10
|
+
from attrs import field
|
|
11
|
+
from .common import UNSET, Unset
|
|
12
|
+
from .core_item import HiveCoreItem
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from ...client import HiveClient
|
|
16
|
+
from .user import User
|
|
17
|
+
|
|
18
|
+
T = TypeVar("T", bound="NotificationNested")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@define
|
|
22
|
+
class NotificationNested(HiveCoreItem):
|
|
23
|
+
"""A lightweight notification model.
|
|
24
|
+
|
|
25
|
+
Attributes:
|
|
26
|
+
id: Unique identifier of the notification.
|
|
27
|
+
from_user_id: Optional user ID that sent the notification.
|
|
28
|
+
comment: Optional comment text.
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
hive_client: "HiveClient"
|
|
33
|
+
id: int
|
|
34
|
+
from_user_id: None | Unset | int = UNSET
|
|
35
|
+
comment: Unset | str = UNSET
|
|
36
|
+
|
|
37
|
+
_from_user: "User | None" = field(init=False, default=None)
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def from_user(self) -> "User | None":
|
|
41
|
+
"""Lazily loads and returns the `User` who sent the notification.
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
A `User` instance or `None` if not available.
|
|
45
|
+
|
|
46
|
+
"""
|
|
47
|
+
if self._from_user is None and not isinstance(self.from_user_id, Unset) and self.from_user_id is not None:
|
|
48
|
+
self._from_user = self.hive_client.get_user(self.from_user_id)
|
|
49
|
+
return self._from_user
|
|
50
|
+
|
|
51
|
+
def to_dict(self) -> dict[str, Any]:
|
|
52
|
+
"""Serialize the notification to a dictionary."""
|
|
53
|
+
field_dict: dict[str, Any] = {
|
|
54
|
+
"id": self.id,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if not isinstance(self.from_user_id, Unset):
|
|
58
|
+
field_dict["from_user"] = self.from_user_id
|
|
59
|
+
|
|
60
|
+
if not isinstance(self.comment, Unset):
|
|
61
|
+
field_dict["comment"] = self.comment
|
|
62
|
+
|
|
63
|
+
return field_dict
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def from_dict(cls, src_dict: Mapping[str, Any], hive_client: "HiveClient") -> Self:
|
|
67
|
+
"""Deserialize the notification from a dictionary."""
|
|
68
|
+
d = dict(src_dict)
|
|
69
|
+
|
|
70
|
+
def _parse_from_user(data: object) -> None | Unset | int:
|
|
71
|
+
if data is None or isinstance(data, Unset):
|
|
72
|
+
return data
|
|
73
|
+
return cast("None | Unset | int", data)
|
|
74
|
+
|
|
75
|
+
return cls(
|
|
76
|
+
hive_client=hive_client,
|
|
77
|
+
id=d.pop("id"),
|
|
78
|
+
from_user_id=_parse_from_user(d.pop("from_user", UNSET)),
|
|
79
|
+
comment=d.pop("comment", UNSET),
|
|
80
|
+
)
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""Model definition for the Hive Program entity.
|
|
2
|
+
|
|
3
|
+
Represents an educational program, including checker configuration,
|
|
4
|
+
sync status, and automatic handling flags.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from collections.abc import Generator, Mapping
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar
|
|
9
|
+
|
|
10
|
+
from attrs import define
|
|
11
|
+
from attrs import field
|
|
12
|
+
from .common import UNSET, Unset
|
|
13
|
+
from .core_item import HiveCoreItem
|
|
14
|
+
from .enums.sync_status_enum import SyncStatusEnum
|
|
15
|
+
from .subject import Subject
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from ...client import HiveClient
|
|
19
|
+
from .class_ import Class
|
|
20
|
+
from .user import User
|
|
21
|
+
|
|
22
|
+
T = TypeVar("T", bound="Program")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@define
|
|
26
|
+
class Program(HiveCoreItem):
|
|
27
|
+
"""Course Program entity.
|
|
28
|
+
|
|
29
|
+
Attributes:
|
|
30
|
+
id: Unique identifier.
|
|
31
|
+
name: Display name of the program.
|
|
32
|
+
checker_id: User ID of the assigned checker.
|
|
33
|
+
sync_status: Sync status (e.g., Normal, Creating).
|
|
34
|
+
sync_message: Optional sync diagnostic message.
|
|
35
|
+
default_class_id: Optional class ID used as default.
|
|
36
|
+
auto_toilet: Auto-toilet generation enabled.
|
|
37
|
+
hanich_raise_hand: Whether hanich can raise hand.
|
|
38
|
+
auto_schedule: Enable auto-scheduling.
|
|
39
|
+
auto_room: Enable automatic room assignments.
|
|
40
|
+
hanich_day_only: Restrict hanich to day-only usage.
|
|
41
|
+
hanich_work_name: Enable work name customization.
|
|
42
|
+
auto_toilet_count: Number of auto toilets to assign.
|
|
43
|
+
hanich_classes_only: Restrict hanich to classes only.
|
|
44
|
+
hanich_schedule: Whether hanich gets scheduled.
|
|
45
|
+
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
hive_client: "HiveClient"
|
|
49
|
+
id: int
|
|
50
|
+
name: str
|
|
51
|
+
checker_id: int
|
|
52
|
+
sync_status: SyncStatusEnum
|
|
53
|
+
sync_message: None | str
|
|
54
|
+
default_class_id: None | Unset | int
|
|
55
|
+
|
|
56
|
+
auto_toilet: Unset | bool = UNSET
|
|
57
|
+
hanich_raise_hand: Unset | bool = UNSET
|
|
58
|
+
auto_schedule: Unset | bool = UNSET
|
|
59
|
+
auto_room: Unset | bool = UNSET
|
|
60
|
+
hanich_day_only: Unset | bool = UNSET
|
|
61
|
+
hanich_work_name: Unset | bool = UNSET
|
|
62
|
+
auto_toilet_count: Unset | int = UNSET
|
|
63
|
+
hanich_classes_only: Unset | bool = UNSET
|
|
64
|
+
hanich_schedule: Unset | bool = UNSET
|
|
65
|
+
|
|
66
|
+
_checker: "User | None" = field(init=False, default=None)
|
|
67
|
+
_default_class: "Class | None" = field(init=False, default=None)
|
|
68
|
+
|
|
69
|
+
def __str__(self) -> str:
|
|
70
|
+
return f"<Program[{self.id}] {self.name}>"
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def checker(self) -> "User":
|
|
74
|
+
"""Lazily loads and returns the checker (staff member)."""
|
|
75
|
+
if self._checker is None:
|
|
76
|
+
self._checker = self.hive_client.get_user(self.checker_id)
|
|
77
|
+
return self._checker
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def default_class(self) -> "Class | None":
|
|
81
|
+
"""Lazily loads the default class, if set."""
|
|
82
|
+
if (
|
|
83
|
+
self._default_class is None
|
|
84
|
+
and not isinstance(self.default_class_id, Unset)
|
|
85
|
+
and self.default_class_id is not None
|
|
86
|
+
):
|
|
87
|
+
self._default_class = self.hive_client.get_class(self.default_class_id)
|
|
88
|
+
return self._default_class
|
|
89
|
+
|
|
90
|
+
def get_subjects(self) -> Generator[Subject]:
|
|
91
|
+
"""Returns all subjects belonging to this program."""
|
|
92
|
+
return self.hive_client.get_subjects(parent_program__id__in=[self.id])
|
|
93
|
+
|
|
94
|
+
def to_dict(self) -> dict[str, Any]:
|
|
95
|
+
field_dict: dict[str, Any] = {
|
|
96
|
+
"id": self.id,
|
|
97
|
+
"name": self.name,
|
|
98
|
+
"checker": self.checker_id,
|
|
99
|
+
"sync_status": self.sync_status.value,
|
|
100
|
+
"sync_message": self.sync_message,
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if not isinstance(self.default_class_id, Unset):
|
|
104
|
+
field_dict["default_class"] = self.default_class_id
|
|
105
|
+
if not isinstance(self.auto_toilet, Unset):
|
|
106
|
+
field_dict["auto_toilet"] = self.auto_toilet
|
|
107
|
+
if not isinstance(self.hanich_raise_hand, Unset):
|
|
108
|
+
field_dict["hanich_raise_hand"] = self.hanich_raise_hand
|
|
109
|
+
if not isinstance(self.auto_schedule, Unset):
|
|
110
|
+
field_dict["auto_schedule"] = self.auto_schedule
|
|
111
|
+
if not isinstance(self.auto_room, Unset):
|
|
112
|
+
field_dict["auto_room"] = self.auto_room
|
|
113
|
+
if not isinstance(self.hanich_day_only, Unset):
|
|
114
|
+
field_dict["hanich_day_only"] = self.hanich_day_only
|
|
115
|
+
if not isinstance(self.hanich_work_name, Unset):
|
|
116
|
+
field_dict["hanich_work_name"] = self.hanich_work_name
|
|
117
|
+
if not isinstance(self.auto_toilet_count, Unset):
|
|
118
|
+
field_dict["auto_toilet_count"] = self.auto_toilet_count
|
|
119
|
+
if not isinstance(self.hanich_classes_only, Unset):
|
|
120
|
+
field_dict["hanich_classes_only"] = self.hanich_classes_only
|
|
121
|
+
if not isinstance(self.hanich_schedule, Unset):
|
|
122
|
+
field_dict["hanich_schedule"] = self.hanich_schedule
|
|
123
|
+
|
|
124
|
+
return field_dict
|
|
125
|
+
|
|
126
|
+
@classmethod
|
|
127
|
+
def from_dict(cls, src_dict: Mapping[str, Any], hive_client: "HiveClient") -> Self:
|
|
128
|
+
"""Create an instance of the class from a dictionary representation.
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
src_dict (Mapping[str, Any]): The source dictionary containing the data to populate the instance.
|
|
132
|
+
hive_client (HiveClient): An instance of HiveClient to associate with the created object.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
Self: An instance of the class populated with data from src_dict.
|
|
136
|
+
|
|
137
|
+
Notes:
|
|
138
|
+
- Handles optional and unset fields using the _parse_optional helper.
|
|
139
|
+
- Converts the 'sync_status' field to a SyncStatusEnum.
|
|
140
|
+
- Pops fields from the dictionary to avoid duplication.
|
|
141
|
+
|
|
142
|
+
"""
|
|
143
|
+
d = dict(src_dict)
|
|
144
|
+
|
|
145
|
+
def _parse_optional(data: object) -> Any:
|
|
146
|
+
if data is None or isinstance(data, Unset):
|
|
147
|
+
return data
|
|
148
|
+
return data
|
|
149
|
+
|
|
150
|
+
return cls(
|
|
151
|
+
id=d.pop("id"),
|
|
152
|
+
name=d.pop("name"),
|
|
153
|
+
checker_id=d.pop("checker"),
|
|
154
|
+
sync_status=SyncStatusEnum(d.pop("sync_status")),
|
|
155
|
+
sync_message=_parse_optional(d.pop("sync_message")),
|
|
156
|
+
default_class_id=_parse_optional(d.pop("default_class", UNSET)),
|
|
157
|
+
auto_toilet=d.pop("auto_toilet", UNSET),
|
|
158
|
+
hanich_raise_hand=d.pop("hanich_raise_hand", UNSET),
|
|
159
|
+
auto_schedule=d.pop("auto_schedule", UNSET),
|
|
160
|
+
auto_room=d.pop("auto_room", UNSET),
|
|
161
|
+
hanich_day_only=d.pop("hanich_day_only", UNSET),
|
|
162
|
+
hanich_work_name=d.pop("hanich_work_name", UNSET),
|
|
163
|
+
auto_toilet_count=d.pop("auto_toilet_count", UNSET),
|
|
164
|
+
hanich_classes_only=d.pop("hanich_classes_only", UNSET),
|
|
165
|
+
hanich_schedule=d.pop("hanich_schedule", UNSET),
|
|
166
|
+
hive_client=hive_client,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
def __eq__(self, value: object) -> bool:
|
|
170
|
+
if not isinstance(value, Program):
|
|
171
|
+
return False
|
|
172
|
+
return (
|
|
173
|
+
self.id == value.id
|
|
174
|
+
and self.checker_id == value.checker_id
|
|
175
|
+
and self.name == value.name
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def __iter__(self) -> Generator["Subject", None, None]:
|
|
179
|
+
"""Allow iteration over this Program to yield its subjects."""
|
|
180
|
+
yield from self.get_subjects()
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Queue model for the Hive API (auto-generated).
|
|
2
|
+
|
|
3
|
+
This module contains the :class:`Queue` dataclass which represents a
|
|
4
|
+
queue entry returned by the Hive API. The class provides simple
|
|
5
|
+
serialization helpers and lazily-resolved relationship properties.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from collections.abc import Mapping
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast
|
|
10
|
+
|
|
11
|
+
from attrs import define
|
|
12
|
+
from attrs import field
|
|
13
|
+
from .common import UNSET, Unset
|
|
14
|
+
from .core_item import HiveCoreItem
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from ...client import HiveClient
|
|
18
|
+
from .module import Module
|
|
19
|
+
from .program import Program
|
|
20
|
+
from .subject import Subject
|
|
21
|
+
from .user import User
|
|
22
|
+
|
|
23
|
+
T = TypeVar("T", bound="Queue")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@define
|
|
27
|
+
class Queue(HiveCoreItem):
|
|
28
|
+
"""Queue model representing a student/program/module queue entry.
|
|
29
|
+
|
|
30
|
+
Attributes mirror the API JSON keys; relationship properties (``user``,
|
|
31
|
+
``module``, ``subject``, ``program``) lazily load the referenced
|
|
32
|
+
objects using the supplied ``hive_client``.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
hive_client: "HiveClient"
|
|
36
|
+
id: int
|
|
37
|
+
name: str
|
|
38
|
+
user_name: None | str
|
|
39
|
+
subject_id: None | int
|
|
40
|
+
subject_name: None | str
|
|
41
|
+
subject_color: None | str
|
|
42
|
+
subject_symbol: None | str
|
|
43
|
+
module_name: None | str
|
|
44
|
+
module_order: None | str
|
|
45
|
+
program_id: int
|
|
46
|
+
program_name: str
|
|
47
|
+
description: None | Unset | str = UNSET
|
|
48
|
+
|
|
49
|
+
module_id: None | Unset | int = UNSET
|
|
50
|
+
user_id: None | Unset | int = UNSET
|
|
51
|
+
|
|
52
|
+
_user: "User | None" = field(init=False, default=None)
|
|
53
|
+
_module: "Module | None" = field(init=False, default=None)
|
|
54
|
+
_subject: "Subject | None" = field(init=False, default=None)
|
|
55
|
+
_program: "Program | None" = field(init=False, default=None)
|
|
56
|
+
|
|
57
|
+
def to_dict(self) -> dict[str, Any]:
|
|
58
|
+
"""Return a JSON-serializable dictionary of this Queue.
|
|
59
|
+
|
|
60
|
+
The returned mapping only includes optional keys when they are not
|
|
61
|
+
:data:`UNSET`.
|
|
62
|
+
"""
|
|
63
|
+
return {
|
|
64
|
+
"id": self.id,
|
|
65
|
+
"name": self.name,
|
|
66
|
+
"user_id": self.user_id,
|
|
67
|
+
"user_name": self.user_name,
|
|
68
|
+
"subject_id": self.subject_id,
|
|
69
|
+
"subject_name": self.subject_name,
|
|
70
|
+
"subject_color": self.subject_color,
|
|
71
|
+
"subject_symbol": self.subject_symbol,
|
|
72
|
+
"module_id": self.module_id,
|
|
73
|
+
"module_name": self.module_name,
|
|
74
|
+
"module_order": self.module_order,
|
|
75
|
+
"program_id": self.program_id,
|
|
76
|
+
"program_name": self.program_name,
|
|
77
|
+
**(
|
|
78
|
+
{"description": self.description}
|
|
79
|
+
if self.description is not UNSET
|
|
80
|
+
else {}
|
|
81
|
+
),
|
|
82
|
+
**({"module": self.module} if self.module is not UNSET else {}),
|
|
83
|
+
**({"user": self.user} if self.user_id is not UNSET else {}),
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def from_dict(cls, src_dict: Mapping[str, Any], hive_client: "HiveClient") -> Self:
|
|
88
|
+
"""Create a :class:`Queue` instance from a mapping (typically parsed JSON).
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
src_dict: Mapping with keys matching the API response.
|
|
92
|
+
hive_client: Hive client used to lazily resolve relationships.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
A populated :class:`Queue` instance.
|
|
96
|
+
"""
|
|
97
|
+
d = dict(src_dict)
|
|
98
|
+
|
|
99
|
+
def _optional(data: object) -> Any:
|
|
100
|
+
return data if not isinstance(data, Unset) else UNSET
|
|
101
|
+
|
|
102
|
+
return cls(
|
|
103
|
+
hive_client=hive_client,
|
|
104
|
+
id=d.pop("id"),
|
|
105
|
+
name=d.pop("name"),
|
|
106
|
+
user_id=cast("None | int", d.pop("user_id")),
|
|
107
|
+
user_name=cast("None | str", d.pop("user_name")),
|
|
108
|
+
subject_id=cast("None | int", d.pop("subject_id")),
|
|
109
|
+
subject_name=cast("None | str", d.pop("subject_name")),
|
|
110
|
+
subject_color=cast("None | str", d.pop("subject_color")),
|
|
111
|
+
subject_symbol=cast("None | str", d.pop("subject_symbol")),
|
|
112
|
+
module_id=cast("None | int", d.pop("module_id")),
|
|
113
|
+
module_name=cast("None | str", d.pop("module_name")),
|
|
114
|
+
module_order=cast("None | str", d.pop("module_order")),
|
|
115
|
+
program_id=d.pop("program_id"),
|
|
116
|
+
program_name=d.pop("program_name"),
|
|
117
|
+
description=_optional(d.pop("description", UNSET)),
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
@property
|
|
121
|
+
def user(self) -> "User | None":
|
|
122
|
+
"""Lazily return the :class:`User` associated with this queue entry.
|
|
123
|
+
|
|
124
|
+
Returns None when no user_id is set.
|
|
125
|
+
"""
|
|
126
|
+
if self._user is None and isinstance(self.user_id, int):
|
|
127
|
+
self._user = self.hive_client.get_user(self.user_id)
|
|
128
|
+
return self._user
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def module(self) -> "Module | None":
|
|
132
|
+
"""Lazily return the :class:`Module` referenced by this queue entry.
|
|
133
|
+
|
|
134
|
+
Returns None when no module_id is present.
|
|
135
|
+
"""
|
|
136
|
+
if self._module is None and isinstance(self.module_id, int):
|
|
137
|
+
self._module = self.hive_client.get_module(self.module_id)
|
|
138
|
+
return self._module
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def subject(self) -> "Subject | None":
|
|
142
|
+
"""Return the resolved :class:`Subject` or None if not available."""
|
|
143
|
+
if isinstance(self.subject_id, int):
|
|
144
|
+
return self.hive_client.get_subject(self.subject_id)
|
|
145
|
+
return None
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def program(self) -> "Program":
|
|
149
|
+
"""Return the resolved :class:`Program` for this queue entry."""
|
|
150
|
+
return self.hive_client.get_program(self.program_id)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""A single item in a learning queue, either referencing an exercise or another queue."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, Union
|
|
5
|
+
|
|
6
|
+
from attrs import define
|
|
7
|
+
from .common import UNSET, Unset
|
|
8
|
+
from .enums.queue_rule_enum import QueueRuleEnum
|
|
9
|
+
from .core_item import HiveCoreItem
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from ...client import HiveClient
|
|
13
|
+
from .exercise import Exercise
|
|
14
|
+
from .queue import Queue
|
|
15
|
+
|
|
16
|
+
T = TypeVar("T", bound="QueueItem")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@define
|
|
20
|
+
class QueueItem(HiveCoreItem):
|
|
21
|
+
"""A single item in a learning queue, either referencing an exercise or another queue."""
|
|
22
|
+
|
|
23
|
+
hive_client: "HiveClient"
|
|
24
|
+
id: int
|
|
25
|
+
order: int
|
|
26
|
+
exercise: Union["Exercise", None]
|
|
27
|
+
nested_queue: Union["Queue", None]
|
|
28
|
+
queue_rule: QueueRuleEnum
|
|
29
|
+
enabled: bool
|
|
30
|
+
continue_on_redo: Unset | bool = UNSET
|
|
31
|
+
|
|
32
|
+
def to_dict(self) -> dict[str, Any]:
|
|
33
|
+
from .exercise import ( # pylint: disable=import-outside-toplevel
|
|
34
|
+
Exercise,
|
|
35
|
+
)
|
|
36
|
+
from .queue import Queue # pylint: disable=import-outside-toplevel
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
"id": self.id,
|
|
40
|
+
"order": self.order,
|
|
41
|
+
"exercise": (
|
|
42
|
+
self.exercise.to_dict()
|
|
43
|
+
if isinstance(self.exercise, Exercise)
|
|
44
|
+
else self.exercise
|
|
45
|
+
),
|
|
46
|
+
"nested_queue": (
|
|
47
|
+
self.nested_queue.to_dict()
|
|
48
|
+
if isinstance(self.nested_queue, Queue)
|
|
49
|
+
else self.nested_queue
|
|
50
|
+
),
|
|
51
|
+
"queue_rule": self.queue_rule.value,
|
|
52
|
+
"enabled": self.enabled,
|
|
53
|
+
**(
|
|
54
|
+
{"continue_on_redo": self.continue_on_redo}
|
|
55
|
+
if self.continue_on_redo is not UNSET
|
|
56
|
+
else {}
|
|
57
|
+
),
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def from_dict(cls, src_dict: Mapping[str, Any], hive_client: "HiveClient") -> Self:
|
|
62
|
+
from .exercise import ( # pylint: disable=import-outside-toplevel
|
|
63
|
+
Exercise,
|
|
64
|
+
)
|
|
65
|
+
from .queue import Queue # pylint: disable=import-outside-toplevel
|
|
66
|
+
|
|
67
|
+
d = dict(src_dict)
|
|
68
|
+
|
|
69
|
+
def _parse_exercise(data: dict[str, Any] | None) -> Union["Exercise", None]:
|
|
70
|
+
if data is None:
|
|
71
|
+
return data
|
|
72
|
+
return Exercise.from_dict(data, hive_client=hive_client)
|
|
73
|
+
|
|
74
|
+
def _parse_nested_queue(data: dict[str, Any] | None) -> Union["Queue", None]:
|
|
75
|
+
if data is None:
|
|
76
|
+
return data
|
|
77
|
+
return Queue.from_dict(data, hive_client=hive_client)
|
|
78
|
+
|
|
79
|
+
return cls(
|
|
80
|
+
hive_client=hive_client,
|
|
81
|
+
id=d.pop("id"),
|
|
82
|
+
order=d.pop("order"),
|
|
83
|
+
exercise=_parse_exercise(d.pop("exercise")),
|
|
84
|
+
nested_queue=_parse_nested_queue(d.pop("nested_queue")),
|
|
85
|
+
queue_rule=QueueRuleEnum(d.pop("queue_rule")),
|
|
86
|
+
enabled=d.pop("enabled"),
|
|
87
|
+
continue_on_redo=d.pop("continue_on_redo", UNSET),
|
|
88
|
+
)
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""Defines the Subject type and related functionality for the Hive API Python bindings."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Generator, Mapping
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast
|
|
5
|
+
|
|
6
|
+
from attrs import define, field
|
|
7
|
+
from .core_item import HiveCoreItem
|
|
8
|
+
from .enums.sync_status_enum import SyncStatusEnum
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from ...client import HiveClient
|
|
12
|
+
from .module import Module
|
|
13
|
+
from .program import Program
|
|
14
|
+
|
|
15
|
+
T = TypeVar("T", bound="Subject")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@define
|
|
19
|
+
class Subject(HiveCoreItem):
|
|
20
|
+
"""Represents a Subject in the Hive system.
|
|
21
|
+
|
|
22
|
+
Attributes:
|
|
23
|
+
hive_client (HiveClient): Reference to the Hive API client.
|
|
24
|
+
id (int): Subject ID.
|
|
25
|
+
symbol (str): Subject symbol.
|
|
26
|
+
parent_program_id (int): ID of the parent Program.
|
|
27
|
+
color (str): Subject color (hex code or name).
|
|
28
|
+
name (str): Display name.
|
|
29
|
+
parent_program_name (str): Name of the parent Program.
|
|
30
|
+
sync_status (SyncStatusEnum): Status of subject synchronization.
|
|
31
|
+
sync_message (str | None): Optional sync error or status message.
|
|
32
|
+
segel_path (str): Staff-accessible path on shared drive.
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
hive_client: "HiveClient"
|
|
37
|
+
id: int
|
|
38
|
+
symbol: str
|
|
39
|
+
parent_program_id: int
|
|
40
|
+
color: str
|
|
41
|
+
name: str
|
|
42
|
+
parent_program_name: str
|
|
43
|
+
sync_status: SyncStatusEnum
|
|
44
|
+
sync_message: str | None
|
|
45
|
+
segel_path: str
|
|
46
|
+
_parent_program: "Program | None" = field(init=False, default=None)
|
|
47
|
+
|
|
48
|
+
def to_dict(self) -> dict[str, Any]:
|
|
49
|
+
"""Serialize the Subject to a dictionary."""
|
|
50
|
+
return {
|
|
51
|
+
"id": self.id,
|
|
52
|
+
"symbol": self.symbol,
|
|
53
|
+
"parent_program": self.parent_program_id,
|
|
54
|
+
"color": self.color,
|
|
55
|
+
"name": self.name,
|
|
56
|
+
"parent_program_name": self.parent_program_name,
|
|
57
|
+
"sync_status": self.sync_status.value,
|
|
58
|
+
"sync_message": self.sync_message,
|
|
59
|
+
"segel_path": self.segel_path,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@classmethod
|
|
63
|
+
def from_dict(cls, src_dict: Mapping[str, Any], hive_client: "HiveClient") -> Self:
|
|
64
|
+
"""Deserialize a Subject from a dictionary.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
src_dict: A dictionary containing Subject data.
|
|
68
|
+
hive_client: An instance of HiveClient.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
A Subject instance.
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
return cls(
|
|
75
|
+
hive_client=hive_client,
|
|
76
|
+
id=src_dict["id"],
|
|
77
|
+
symbol=src_dict["symbol"],
|
|
78
|
+
parent_program_id=src_dict["parent_program"],
|
|
79
|
+
color=src_dict["color"],
|
|
80
|
+
name=src_dict["name"],
|
|
81
|
+
parent_program_name=src_dict["parent_program_name"],
|
|
82
|
+
sync_status=SyncStatusEnum(src_dict["sync_status"]),
|
|
83
|
+
sync_message=cast("str | None", src_dict.get("sync_message")),
|
|
84
|
+
segel_path=src_dict["segel_path"],
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def parent_program(self) -> "Program":
|
|
89
|
+
"""Lazily load and return the parent Program.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Program: The parent program instance.
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
if self._parent_program is None:
|
|
96
|
+
self._parent_program = self.hive_client.get_program(self.parent_program_id)
|
|
97
|
+
return self._parent_program
|
|
98
|
+
|
|
99
|
+
def get_modules(self) -> Generator["Module"]:
|
|
100
|
+
"""Retrieve all modules associated with this subject.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Generator[Module]: Generator of Module instances.
|
|
104
|
+
|
|
105
|
+
"""
|
|
106
|
+
return self.hive_client.get_modules(parent_subject__id=self.id)
|
|
107
|
+
|
|
108
|
+
def get_module(self, module_name: str) -> "Module":
|
|
109
|
+
"""Retrieve a specific module by name within this subject.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
module_name (str): The name of the module to retrieve.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
Module: The Module instance if found.
|
|
116
|
+
|
|
117
|
+
"""
|
|
118
|
+
modules = list(
|
|
119
|
+
self.hive_client.get_modules(
|
|
120
|
+
parent_subject__id=self.id, module_name=module_name
|
|
121
|
+
)
|
|
122
|
+
)
|
|
123
|
+
if len(modules) == 0:
|
|
124
|
+
raise ValueError(
|
|
125
|
+
f"Module '{module_name}' not found in subject '{self.name}'"
|
|
126
|
+
)
|
|
127
|
+
if len(modules) > 1:
|
|
128
|
+
raise ValueError(
|
|
129
|
+
f"Multiple modules named '{module_name}' found in subject '{self.name}'"
|
|
130
|
+
)
|
|
131
|
+
return modules[0]
|
|
132
|
+
|
|
133
|
+
def __eq__(self, value: object) -> bool:
|
|
134
|
+
if not isinstance(value, Subject):
|
|
135
|
+
return False
|
|
136
|
+
return self.id == value.id and self.parent_program == value.parent_program
|
|
137
|
+
|
|
138
|
+
def __lt__(self, value: object) -> bool:
|
|
139
|
+
if not isinstance(value, Subject):
|
|
140
|
+
return NotImplemented
|
|
141
|
+
return self.symbol < value.symbol
|
|
142
|
+
|
|
143
|
+
def __iter__(self) -> Generator["Module", None, None]:
|
|
144
|
+
"""Allow iteration over this Subject to yield its modules."""
|
|
145
|
+
yield from self.get_modules()
|
|
146
|
+
|
|
147
|
+
def __hash__(self) -> int:
|
|
148
|
+
return hash(
|
|
149
|
+
(
|
|
150
|
+
self.id,
|
|
151
|
+
self.parent_program_id,
|
|
152
|
+
)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
SubjectLike = TypeVar("SubjectLike", Subject, int)
|