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,15 @@
|
|
|
1
|
+
"""Enumeration for synchronization status (auto-generated)."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SyncStatusEnum(str, Enum):
|
|
7
|
+
"""Enumeration of possible synchronization statuses."""
|
|
8
|
+
|
|
9
|
+
CREATING = "Creating"
|
|
10
|
+
DELETING = "Deleting"
|
|
11
|
+
ERROR = "Error"
|
|
12
|
+
NORMAL = "Normal"
|
|
13
|
+
|
|
14
|
+
def __str__(self) -> str:
|
|
15
|
+
return str(self.value)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Enumeration for visibility levels of help requests."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class VisibilityEnum(str, Enum):
|
|
7
|
+
"""Enumeration of visibility levels for help requests."""
|
|
8
|
+
|
|
9
|
+
ALL_STAFF = "All Staff"
|
|
10
|
+
ALL_STAFF_AND_CHECKERS = "All Staff And Checkers"
|
|
11
|
+
AUTHOR_ONLY = "Author Only"
|
|
12
|
+
|
|
13
|
+
def __str__(self) -> str:
|
|
14
|
+
return str(self.value)
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""Model definition for calendar events in the Hive system.
|
|
2
|
+
|
|
3
|
+
Represents a scheduled item such as a lecture, workshop, or PATBAS session,
|
|
4
|
+
including timing, participants, subject, and related module.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import datetime
|
|
8
|
+
from collections.abc import Mapping
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast
|
|
10
|
+
|
|
11
|
+
from attrs import define
|
|
12
|
+
from dateutil.parser import isoparse
|
|
13
|
+
from .common import UNSET, Unset
|
|
14
|
+
from .core_item import HiveCoreItem
|
|
15
|
+
from .enums.event_type_enum import EventTypeEnum
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from ...client import HiveClient
|
|
19
|
+
from .event_attendees_type_0_item import EventAttendeesType0Item
|
|
20
|
+
|
|
21
|
+
T = TypeVar("T", bound="Event")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@define
|
|
25
|
+
class Event(HiveCoreItem):
|
|
26
|
+
"""Calendar event model.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
start: Event start datetime (ISO 8601).
|
|
30
|
+
end: Event end datetime.
|
|
31
|
+
title: Optional title.
|
|
32
|
+
attendees: Optional list of attendees.
|
|
33
|
+
subject_id: Optional related subject ID.
|
|
34
|
+
subject_name: Optional subject display name.
|
|
35
|
+
color: Optional display color for UI.
|
|
36
|
+
type_: Event type (e.g. Patbas, Lecture).
|
|
37
|
+
module_id: Optional associated module ID.
|
|
38
|
+
lesson_name: Optional lesson name.
|
|
39
|
+
location: Optional physical or virtual location.
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
start: datetime.datetime
|
|
44
|
+
end: datetime.datetime
|
|
45
|
+
title: None | str
|
|
46
|
+
attendees: None | list["EventAttendeesType0Item"]
|
|
47
|
+
subject_id: None | int
|
|
48
|
+
subject_name: None | str
|
|
49
|
+
color: None | str
|
|
50
|
+
type_: EventTypeEnum
|
|
51
|
+
module_id: None | int
|
|
52
|
+
lesson_name: None | str
|
|
53
|
+
location: None | Unset | str = UNSET
|
|
54
|
+
|
|
55
|
+
def to_dict(self) -> dict[str, Any]:
|
|
56
|
+
start = self.start.isoformat()
|
|
57
|
+
end = self.end.isoformat()
|
|
58
|
+
|
|
59
|
+
attendees: None | list[dict[str, Any]]
|
|
60
|
+
attendees = (
|
|
61
|
+
[a.to_dict() for a in self.attendees]
|
|
62
|
+
if isinstance(self.attendees, list)
|
|
63
|
+
else self.attendees
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
location = UNSET if isinstance(self.location, Unset) else self.location
|
|
67
|
+
|
|
68
|
+
field_dict: dict[str, Any] = {
|
|
69
|
+
"start": start,
|
|
70
|
+
"end": end,
|
|
71
|
+
"title": self.title,
|
|
72
|
+
"attendees": attendees,
|
|
73
|
+
"subject_id": self.subject_id,
|
|
74
|
+
"subject_name": self.subject_name,
|
|
75
|
+
"color": self.color,
|
|
76
|
+
"type": self.type_.value,
|
|
77
|
+
"module_id": self.module_id,
|
|
78
|
+
"lesson_name": self.lesson_name,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if location is not UNSET:
|
|
82
|
+
field_dict["location"] = location
|
|
83
|
+
|
|
84
|
+
return field_dict
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def from_dict(cls, src_dict: Mapping[str, Any], hive_client: "HiveClient") -> Self:
|
|
88
|
+
from .event_attendees_type_0_item import EventAttendeesType0Item # pylint: disable=import-outside-toplevel
|
|
89
|
+
|
|
90
|
+
d = dict(src_dict)
|
|
91
|
+
|
|
92
|
+
def _parse_optional_str(data: object) -> None | str:
|
|
93
|
+
return data if data is None else cast("str", data)
|
|
94
|
+
|
|
95
|
+
def _parse_optional_int(data: object) -> None | int:
|
|
96
|
+
return data if data is None else cast("int", data)
|
|
97
|
+
|
|
98
|
+
def _parse_optional_list(data: object) -> None | list[EventAttendeesType0Item]:
|
|
99
|
+
if data is None:
|
|
100
|
+
return None
|
|
101
|
+
try:
|
|
102
|
+
return [EventAttendeesType0Item.from_dict(item, hive_client=hive_client) for item in data]
|
|
103
|
+
except Exception: # pylint: disable=broad-except
|
|
104
|
+
return cast("None | list[EventAttendeesType0Item]", data)
|
|
105
|
+
|
|
106
|
+
def _parse_optional_unset_str(data: object) -> None | Unset | str:
|
|
107
|
+
if data is None or isinstance(data, Unset):
|
|
108
|
+
return data
|
|
109
|
+
return cast("str", data)
|
|
110
|
+
|
|
111
|
+
return cls(
|
|
112
|
+
start=isoparse(d.pop("start")),
|
|
113
|
+
end=isoparse(d.pop("end")),
|
|
114
|
+
title=_parse_optional_str(d.pop("title")),
|
|
115
|
+
attendees=_parse_optional_list(d.pop("attendees")),
|
|
116
|
+
subject_id=_parse_optional_int(d.pop("subject_id")),
|
|
117
|
+
subject_name=_parse_optional_str(d.pop("subject_name")),
|
|
118
|
+
color=_parse_optional_str(d.pop("color")),
|
|
119
|
+
type_=EventTypeEnum(d.pop("type")),
|
|
120
|
+
module_id=_parse_optional_int(d.pop("module_id")),
|
|
121
|
+
lesson_name=_parse_optional_str(d.pop("lesson_name")),
|
|
122
|
+
location=_parse_optional_unset_str(d.pop("location", UNSET)),
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
def __eq__(self, value: object) -> bool:
|
|
126
|
+
if not isinstance(value, Event):
|
|
127
|
+
return False
|
|
128
|
+
return (
|
|
129
|
+
self.start == value.start
|
|
130
|
+
and self.end == value.end
|
|
131
|
+
and self.title == value.title
|
|
132
|
+
and self.attendees == value.attendees
|
|
133
|
+
and self.subject_id == value.subject_id
|
|
134
|
+
and self.subject_name == value.subject_name
|
|
135
|
+
and self.color == value.color
|
|
136
|
+
and self.type_ == value.type_
|
|
137
|
+
and self.module_id == value.module_id
|
|
138
|
+
and self.lesson_name == value.lesson_name
|
|
139
|
+
and self.location == value.location
|
|
140
|
+
)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""EventAttendeesType0Item type class module."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar
|
|
5
|
+
|
|
6
|
+
from attrs import define
|
|
7
|
+
|
|
8
|
+
from .core_item import HiveCoreItem
|
|
9
|
+
from .common import UNSET, Unset
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from ...client import HiveClient
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T", bound="EventAttendeesType0Item")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@define
|
|
18
|
+
class EventAttendeesType0Item(HiveCoreItem):
|
|
19
|
+
"""Attributes:
|
|
20
|
+
name (str):
|
|
21
|
+
id (int):
|
|
22
|
+
description (Union[Unset, str]):
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
hive_client: "HiveClient"
|
|
27
|
+
name: str
|
|
28
|
+
id: int
|
|
29
|
+
description: Unset | str = UNSET
|
|
30
|
+
|
|
31
|
+
def to_dict(self) -> dict[str, Any]:
|
|
32
|
+
name = self.name
|
|
33
|
+
|
|
34
|
+
id = self.id
|
|
35
|
+
|
|
36
|
+
description = self.description
|
|
37
|
+
|
|
38
|
+
field_dict: dict[str, Any] = {}
|
|
39
|
+
field_dict.update(
|
|
40
|
+
{
|
|
41
|
+
"name": name,
|
|
42
|
+
"id": id,
|
|
43
|
+
},
|
|
44
|
+
)
|
|
45
|
+
if description is not UNSET:
|
|
46
|
+
field_dict["description"] = description
|
|
47
|
+
|
|
48
|
+
return field_dict
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_dict(cls, src_dict: Mapping[str, Any], hive_client: "HiveClient") -> Self:
|
|
52
|
+
d = dict(src_dict)
|
|
53
|
+
name = d.pop("name")
|
|
54
|
+
|
|
55
|
+
id = d.pop("id")
|
|
56
|
+
|
|
57
|
+
description = d.pop("description", UNSET)
|
|
58
|
+
|
|
59
|
+
return cls(
|
|
60
|
+
name=name,
|
|
61
|
+
id=id,
|
|
62
|
+
description=description,
|
|
63
|
+
hive_client=hive_client,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def __eq__(self, value: object) -> bool:
|
|
67
|
+
if not isinstance(value, EventAttendeesType0Item):
|
|
68
|
+
return False
|
|
69
|
+
return self.id == value.id
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Module for EventColor type."""
|
|
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="EventColor")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@define
|
|
16
|
+
class EventColor(HiveCoreItem):
|
|
17
|
+
"""Attributes:
|
|
18
|
+
id (int):
|
|
19
|
+
name (str):
|
|
20
|
+
color (str):
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
id: int
|
|
25
|
+
name: str
|
|
26
|
+
color: str
|
|
27
|
+
hive_client: "HiveClient"
|
|
28
|
+
|
|
29
|
+
def to_dict(self) -> dict[str, Any]:
|
|
30
|
+
"""Converts the EventColor instance to a dictionary."""
|
|
31
|
+
id = self.id
|
|
32
|
+
|
|
33
|
+
name = self.name
|
|
34
|
+
|
|
35
|
+
color = self.color
|
|
36
|
+
|
|
37
|
+
field_dict: dict[str, Any] = {}
|
|
38
|
+
field_dict.update(
|
|
39
|
+
{
|
|
40
|
+
"id": id,
|
|
41
|
+
"name": name,
|
|
42
|
+
"color": color,
|
|
43
|
+
},
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return field_dict
|
|
47
|
+
|
|
48
|
+
@classmethod
|
|
49
|
+
def from_dict(cls, src_dict: Mapping[str, Any], hive_client: "HiveClient") -> Self:
|
|
50
|
+
"""Creates an EventColor instance from a dictionary."""
|
|
51
|
+
d = dict(src_dict)
|
|
52
|
+
id = d.pop("id")
|
|
53
|
+
|
|
54
|
+
name = d.pop("name")
|
|
55
|
+
|
|
56
|
+
color = d.pop("color")
|
|
57
|
+
|
|
58
|
+
return cls(
|
|
59
|
+
id=id,
|
|
60
|
+
name=name,
|
|
61
|
+
color=color,
|
|
62
|
+
hive_client=hive_client,
|
|
63
|
+
)
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""Model for exercises in course modules."""
|
|
2
|
+
|
|
3
|
+
from typing import Generator, TYPE_CHECKING, Any, Self, TypeVar, cast
|
|
4
|
+
|
|
5
|
+
from attrs import define, field
|
|
6
|
+
from .common import UNSET, Unset
|
|
7
|
+
from .core_item import HiveCoreItem
|
|
8
|
+
from .enums.exercise_patbas_enum import PatbasEnum
|
|
9
|
+
from .enums.exercise_preview_types import ExercisePreviewTypes
|
|
10
|
+
from .enums.sync_status_enum import SyncStatusEnum
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from ...client import HiveClient
|
|
14
|
+
from .module import Module
|
|
15
|
+
from .subject import Subject
|
|
16
|
+
from .assignment import Assignment
|
|
17
|
+
|
|
18
|
+
T = TypeVar("T", bound="Exercise")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@define
|
|
22
|
+
class Exercise(HiveCoreItem):
|
|
23
|
+
"""Represents an exercise in a course module.
|
|
24
|
+
|
|
25
|
+
Attributes:
|
|
26
|
+
id: Unique exercise ID.
|
|
27
|
+
name: Exercise name.
|
|
28
|
+
parent_module_id: ID of the module the exercise belongs to.
|
|
29
|
+
parent_subject_id: ID of the subject the exercise belongs to.
|
|
30
|
+
parent_module_name: Name of the module.
|
|
31
|
+
parent_subject_symbol: Symbol of the subject.
|
|
32
|
+
parent_subject_color: Color tag of the subject.
|
|
33
|
+
download: Whether the exercise is downloadable.
|
|
34
|
+
preview: The preview method.
|
|
35
|
+
parent_subject_name: Name of the subject.
|
|
36
|
+
parent_module_order: Display order of the module.
|
|
37
|
+
order: Display order of the exercise.
|
|
38
|
+
tags: List of tag strings.
|
|
39
|
+
patbas: PATBAS mode.
|
|
40
|
+
sync_status: Synchronization status.
|
|
41
|
+
sync_message: Optional sync error message.
|
|
42
|
+
segel_path: Path to the exercise on the staff network.
|
|
43
|
+
patbas_preview: Optional preview type for PATBAS.
|
|
44
|
+
patbas_download: Whether PATBAS allows download.
|
|
45
|
+
is_lecture: Whether this is a lecture.
|
|
46
|
+
style: Optional style.
|
|
47
|
+
on_creation_data: Optional metadata used on creation.
|
|
48
|
+
autocheck_tag: Optional tag for auto-checking.
|
|
49
|
+
autodone: Whether it can be automatically marked done.
|
|
50
|
+
expected_duration: Optional string representing duration.
|
|
51
|
+
segel_brief: Optional brief description.
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
hive_client: "HiveClient"
|
|
56
|
+
id: int
|
|
57
|
+
name: str
|
|
58
|
+
parent_module_id: int
|
|
59
|
+
parent_subject_id: int
|
|
60
|
+
parent_module_name: str
|
|
61
|
+
parent_subject_symbol: str
|
|
62
|
+
parent_subject_color: str
|
|
63
|
+
download: bool
|
|
64
|
+
preview: ExercisePreviewTypes
|
|
65
|
+
parent_subject_name: str
|
|
66
|
+
parent_module_order: str
|
|
67
|
+
order: str
|
|
68
|
+
tags: list[str]
|
|
69
|
+
patbas: PatbasEnum
|
|
70
|
+
sync_status: SyncStatusEnum
|
|
71
|
+
sync_message: None | str
|
|
72
|
+
segel_path: str
|
|
73
|
+
patbas_preview: Unset | ExercisePreviewTypes = UNSET
|
|
74
|
+
patbas_download: Unset | bool = UNSET
|
|
75
|
+
is_lecture: Unset | bool = UNSET
|
|
76
|
+
style: None | Unset | str = UNSET
|
|
77
|
+
on_creation_data: Unset | Any = UNSET
|
|
78
|
+
autocheck_tag: None | Unset | str = UNSET
|
|
79
|
+
autodone: Unset | bool = UNSET
|
|
80
|
+
expected_duration: None | Unset | str = UNSET
|
|
81
|
+
segel_brief: Unset | str = UNSET
|
|
82
|
+
|
|
83
|
+
_parent_module: "Module | None" = field(init=False, default=None)
|
|
84
|
+
_parent_subject: "Subject | None" = field(init=False, default=None)
|
|
85
|
+
|
|
86
|
+
@property
|
|
87
|
+
def parent_module(self) -> "Module":
|
|
88
|
+
"""Lazily load the module this exercise belongs to."""
|
|
89
|
+
if self._parent_module is None:
|
|
90
|
+
self._parent_module = self.hive_client.get_module(self.parent_module_id)
|
|
91
|
+
return self._parent_module
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def parent_subject(self) -> "Subject":
|
|
95
|
+
"""Lazily load the subject this exercise belongs to."""
|
|
96
|
+
if self._parent_subject is None:
|
|
97
|
+
self._parent_subject = self.hive_client.get_subject(self.parent_subject_id)
|
|
98
|
+
return self._parent_subject
|
|
99
|
+
|
|
100
|
+
def to_dict(self) -> dict[str, Any]:
|
|
101
|
+
"""Serialize the Exercise to a dictionary."""
|
|
102
|
+
result: dict[str, Any] = {
|
|
103
|
+
"id": self.id,
|
|
104
|
+
"name": self.name,
|
|
105
|
+
"parent_module": self.parent_module_id,
|
|
106
|
+
"parent_subject": self.parent_subject_id,
|
|
107
|
+
"parent_module_name": self.parent_module_name,
|
|
108
|
+
"parent_subject_symbol": self.parent_subject_symbol,
|
|
109
|
+
"parent_subject_color": self.parent_subject_color,
|
|
110
|
+
"download": self.download,
|
|
111
|
+
"preview": self.preview.value,
|
|
112
|
+
"parent_subject_name": self.parent_subject_name,
|
|
113
|
+
"parent_module_order": self.parent_module_order,
|
|
114
|
+
"order": self.order,
|
|
115
|
+
"tags": self.tags,
|
|
116
|
+
"patbas": self.patbas.value,
|
|
117
|
+
"sync_status": self.sync_status.value,
|
|
118
|
+
"sync_message": self.sync_message,
|
|
119
|
+
"segel_path": self.segel_path,
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if not isinstance(self.patbas_preview, Unset):
|
|
123
|
+
result["patbas_preview"] = self.patbas_preview.value
|
|
124
|
+
if not isinstance(self.patbas_download, Unset):
|
|
125
|
+
result["patbas_download"] = self.patbas_download
|
|
126
|
+
if not isinstance(self.is_lecture, Unset):
|
|
127
|
+
result["is_lecture"] = self.is_lecture
|
|
128
|
+
if not isinstance(self.style, Unset):
|
|
129
|
+
result["style"] = self.style
|
|
130
|
+
if not isinstance(self.on_creation_data, Unset):
|
|
131
|
+
result["on_creation_data"] = self.on_creation_data
|
|
132
|
+
if not isinstance(self.autocheck_tag, Unset):
|
|
133
|
+
result["autocheck_tag"] = self.autocheck_tag
|
|
134
|
+
if not isinstance(self.autodone, Unset):
|
|
135
|
+
result["autodone"] = self.autodone
|
|
136
|
+
if not isinstance(self.expected_duration, Unset):
|
|
137
|
+
result["expected_duration"] = self.expected_duration
|
|
138
|
+
if not isinstance(self.segel_brief, Unset):
|
|
139
|
+
result["segel_brief"] = self.segel_brief
|
|
140
|
+
|
|
141
|
+
return result
|
|
142
|
+
|
|
143
|
+
@classmethod
|
|
144
|
+
def from_dict(cls, src_dict: dict[str, Any], hive_client: "HiveClient") -> Self:
|
|
145
|
+
"""Deserialize Exercise from dictionary."""
|
|
146
|
+
d = dict(src_dict)
|
|
147
|
+
|
|
148
|
+
return cls(
|
|
149
|
+
hive_client=hive_client,
|
|
150
|
+
id=d["id"],
|
|
151
|
+
name=d["name"],
|
|
152
|
+
parent_module_id=d["parent_module"],
|
|
153
|
+
parent_subject_id=d["parent_subject"],
|
|
154
|
+
parent_module_name=d["parent_module_name"],
|
|
155
|
+
parent_subject_symbol=d["parent_subject_symbol"],
|
|
156
|
+
parent_subject_color=d["parent_subject_color"],
|
|
157
|
+
download=d["download"],
|
|
158
|
+
preview=ExercisePreviewTypes(d["preview"]),
|
|
159
|
+
parent_subject_name=d["parent_subject_name"],
|
|
160
|
+
parent_module_order=d["parent_module_order"],
|
|
161
|
+
order=d["order"],
|
|
162
|
+
tags=cast("list[str]", d["tags"]),
|
|
163
|
+
patbas=PatbasEnum(d["patbas"]),
|
|
164
|
+
sync_status=SyncStatusEnum(d["sync_status"]),
|
|
165
|
+
sync_message=cast("str | None", d["sync_message"]),
|
|
166
|
+
segel_path=d["segel_path"],
|
|
167
|
+
patbas_preview=(
|
|
168
|
+
UNSET
|
|
169
|
+
if isinstance((val := d.get("patbas_preview", UNSET)), Unset)
|
|
170
|
+
else ExercisePreviewTypes(val)
|
|
171
|
+
),
|
|
172
|
+
patbas_download=d.get("patbas_download", UNSET),
|
|
173
|
+
is_lecture=d.get("is_lecture", UNSET),
|
|
174
|
+
style=cast("str | None | Unset", d.get("style", UNSET)),
|
|
175
|
+
on_creation_data=d.get("on_creation_data", UNSET),
|
|
176
|
+
autocheck_tag=cast("str | None | Unset", d.get("autocheck_tag", UNSET)),
|
|
177
|
+
autodone=d.get("autodone", UNSET),
|
|
178
|
+
expected_duration=cast(
|
|
179
|
+
"str | None | Unset", d.get("expected_duration", UNSET)
|
|
180
|
+
),
|
|
181
|
+
segel_brief=cast("str | Unset", d.get("segel_brief", UNSET)),
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def __eq__(self, value: object) -> bool:
|
|
185
|
+
if not isinstance(value, Exercise):
|
|
186
|
+
return False
|
|
187
|
+
return self.id == value.id and self.parent_module == value.parent_module
|
|
188
|
+
|
|
189
|
+
def __lt__(self, value: object) -> bool:
|
|
190
|
+
if not isinstance(value, Exercise):
|
|
191
|
+
return NotImplemented
|
|
192
|
+
return self.order < value.order
|
|
193
|
+
|
|
194
|
+
def get_assignments(self) -> Generator["Assignment", None, None]:
|
|
195
|
+
"""Fetch all assignments associated with this exercise."""
|
|
196
|
+
return self.hive_client.get_assignments(
|
|
197
|
+
exercise__id=self.id,
|
|
198
|
+
exercise__parent_module__id=self.parent_module_id,
|
|
199
|
+
exercise__parent_module__parent_subject__id=self.parent_subject_id,
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
def __iter__(self) -> Generator["Assignment", None, None]:
|
|
203
|
+
"""Allow iteration over this Exercise to yield its assignments."""
|
|
204
|
+
yield from self.get_assignments()
|
|
205
|
+
|
|
206
|
+
def __hash__(self) -> int:
|
|
207
|
+
return hash(
|
|
208
|
+
(
|
|
209
|
+
self.id,
|
|
210
|
+
self.parent_module_id,
|
|
211
|
+
self.parent_subject_id,
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
ExerciseLike = TypeVar("ExerciseLike", Exercise, int)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""Model definition for a form field used in questionnaires or structured input forms within Hive.
|
|
2
|
+
|
|
3
|
+
Represents a field definition with constraints and metadata,
|
|
4
|
+
including optional validation and visibility toggles.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from collections.abc import Mapping
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast
|
|
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.form_field_type_enum import FormFieldTypeEnum
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from ...client import HiveClient
|
|
18
|
+
from .program import Class
|
|
19
|
+
|
|
20
|
+
T = TypeVar("T", bound="FormField")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@define
|
|
24
|
+
class FormField(HiveCoreItem):
|
|
25
|
+
"""Represents a single field in a dynamic form.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
id: Field ID.
|
|
29
|
+
name: Name of the field.
|
|
30
|
+
type_: Field type (e.g., text, number, multiple).
|
|
31
|
+
order: Position of the field in the form.
|
|
32
|
+
required: Whether this field must be filled out.
|
|
33
|
+
staff_responses: Whether staff members can respond.
|
|
34
|
+
hanich_responses: Whether students can respond.
|
|
35
|
+
has_value: Whether the field currently holds a value.
|
|
36
|
+
segel_only: Whether the field is visible only to Segel (staff).
|
|
37
|
+
description: Optional description of the field.
|
|
38
|
+
lower_limit: Optional lower numeric limit.
|
|
39
|
+
upper_limit: Optional upper numeric limit.
|
|
40
|
+
choices: Optional list of string choices (for multiple/multiResponse).
|
|
41
|
+
metadata: Additional arbitrary metadata for the field.
|
|
42
|
+
groups: Optional list of group IDs the field is associated with.
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
hive_client: "HiveClient"
|
|
47
|
+
id: int
|
|
48
|
+
name: str
|
|
49
|
+
type_: FormFieldTypeEnum
|
|
50
|
+
order: int
|
|
51
|
+
required: bool
|
|
52
|
+
staff_responses: bool
|
|
53
|
+
hanich_responses: bool
|
|
54
|
+
has_value: bool
|
|
55
|
+
segel_only: bool
|
|
56
|
+
description: Unset | str = UNSET
|
|
57
|
+
lower_limit: None | Unset | int = UNSET
|
|
58
|
+
upper_limit: None | Unset | int = UNSET
|
|
59
|
+
choices: None | Unset | list[str] = UNSET
|
|
60
|
+
metadata: Unset | Any = UNSET
|
|
61
|
+
group_ids: Unset | list[int] = UNSET
|
|
62
|
+
_groups: "list[Class] | None" = field(init=False, default=None)
|
|
63
|
+
|
|
64
|
+
def to_dict(self) -> dict[str, Any]:
|
|
65
|
+
return {
|
|
66
|
+
"id": self.id,
|
|
67
|
+
"name": self.name,
|
|
68
|
+
"type": self.type_.value,
|
|
69
|
+
"order": self.order,
|
|
70
|
+
"required": self.required,
|
|
71
|
+
"staff_responses": self.staff_responses,
|
|
72
|
+
"hanich_responses": self.hanich_responses,
|
|
73
|
+
"has_value": self.has_value,
|
|
74
|
+
"segel_only": self.segel_only,
|
|
75
|
+
**(
|
|
76
|
+
{"description": self.description}
|
|
77
|
+
if self.description is not UNSET
|
|
78
|
+
else {}
|
|
79
|
+
),
|
|
80
|
+
**(
|
|
81
|
+
{"lower_limit": self.lower_limit}
|
|
82
|
+
if self.lower_limit is not UNSET
|
|
83
|
+
else {}
|
|
84
|
+
),
|
|
85
|
+
**(
|
|
86
|
+
{"upper_limit": self.upper_limit}
|
|
87
|
+
if self.upper_limit is not UNSET
|
|
88
|
+
else {}
|
|
89
|
+
),
|
|
90
|
+
**({"choices": self.choices} if self.choices is not UNSET else {}),
|
|
91
|
+
**({"metadata": self.metadata} if self.metadata is not UNSET else {}),
|
|
92
|
+
**({"groups": self.group_ids} if self.group_ids is not UNSET else {}),
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def from_dict(cls, src_dict: Mapping[str, Any], hive_client: "HiveClient") -> Self:
|
|
97
|
+
d = dict(src_dict)
|
|
98
|
+
|
|
99
|
+
def _parse_optional_int(data: object) -> None | Unset | int:
|
|
100
|
+
if data is None or isinstance(data, Unset):
|
|
101
|
+
return data
|
|
102
|
+
return cast("int", data)
|
|
103
|
+
|
|
104
|
+
def _parse_choices(data: object) -> None | Unset | list[str]:
|
|
105
|
+
if data is None or isinstance(data, Unset):
|
|
106
|
+
return data
|
|
107
|
+
if not isinstance(data, list):
|
|
108
|
+
return UNSET
|
|
109
|
+
return cast("list[str]", data)
|
|
110
|
+
|
|
111
|
+
return cls(
|
|
112
|
+
hive_client=hive_client,
|
|
113
|
+
id=d.pop("id"),
|
|
114
|
+
name=d.pop("name"),
|
|
115
|
+
type_=FormFieldTypeEnum(d.pop("type")),
|
|
116
|
+
order=d.pop("order"),
|
|
117
|
+
required=d.pop("required"),
|
|
118
|
+
staff_responses=d.pop("staff_responses"),
|
|
119
|
+
hanich_responses=d.pop("hanich_responses"),
|
|
120
|
+
has_value=d.pop("has_value"),
|
|
121
|
+
segel_only=d.pop("segel_only"),
|
|
122
|
+
description=d.pop("description", UNSET),
|
|
123
|
+
lower_limit=_parse_optional_int(d.pop("lower_limit", UNSET)),
|
|
124
|
+
upper_limit=_parse_optional_int(d.pop("upper_limit", UNSET)),
|
|
125
|
+
choices=_parse_choices(d.pop("choices", UNSET)),
|
|
126
|
+
metadata=d.pop("metadata", UNSET),
|
|
127
|
+
group_ids=cast("Unset | list[int]", d.pop("groups", UNSET)),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def groups(self) -> list["Class"]:
|
|
132
|
+
"""Return the list of Classes which this field is relevant to."""
|
|
133
|
+
if isinstance(self.group_ids, Unset):
|
|
134
|
+
return []
|
|
135
|
+
if self._groups is None:
|
|
136
|
+
self._groups = [
|
|
137
|
+
self.hive_client.get_class(group_id) for group_id in self.group_ids
|
|
138
|
+
]
|
|
139
|
+
return self._groups
|
|
140
|
+
|
|
141
|
+
def __eq__(self, value: object) -> bool:
|
|
142
|
+
if not isinstance(value, FormField):
|
|
143
|
+
return False
|
|
144
|
+
return self.id == value.id
|
|
145
|
+
|
|
146
|
+
def __lt__(self, value: object) -> bool:
|
|
147
|
+
if not isinstance(value, FormField):
|
|
148
|
+
return NotImplemented
|
|
149
|
+
return self.order < value.order
|
|
150
|
+
|
|
151
|
+
def __hash__(self) -> int:
|
|
152
|
+
return hash((self.id,))
|