PyHiveLMS 5.12.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/client.py +355 -0
- pyhive/src/__init__.py +0 -0
- pyhive/src/authenticated_hive_client.py +250 -0
- pyhive/src/types/__init__.py +0 -0
- pyhive/src/types/assignment.py +192 -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_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 +192 -0
- pyhive/src/types/form_field.py +149 -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 +107 -0
- pyhive/src/types/notification_nested.py +80 -0
- pyhive/src/types/program.py +172 -0
- pyhive/src/types/queue.py +150 -0
- pyhive/src/types/queue_item.py +88 -0
- pyhive/src/types/subject.py +116 -0
- pyhive/src/types/tag.py +62 -0
- pyhive/src/types/user.py +375 -0
- pyhivelms-5.12.0.dist-info/METADATA +92 -0
- pyhivelms-5.12.0.dist-info/RECORD +45 -0
- pyhivelms-5.12.0.dist-info/WHEEL +4 -0
|
@@ -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 as _attrs_define
|
|
12
|
+
from dateutil.parser import isoparse
|
|
13
|
+
from src.types.common import UNSET, Unset
|
|
14
|
+
from src.types.core_item import HiveCoreItem
|
|
15
|
+
from src.types.enums.event_type_enum import EventTypeEnum
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from client import HiveClient
|
|
19
|
+
from src.types.event_attendees_type_0_item import EventAttendeesType0Item
|
|
20
|
+
|
|
21
|
+
T = TypeVar("T", bound="Event")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@_attrs_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 src.types.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 as _attrs_define
|
|
7
|
+
|
|
8
|
+
from src.types.core_item import HiveCoreItem
|
|
9
|
+
from src.types.common import UNSET, Unset
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from client import HiveClient
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T", bound="EventAttendeesType0Item")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@_attrs_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 src.types.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,192 @@
|
|
|
1
|
+
"""Model for exercises in course modules."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Self, TypeVar, cast
|
|
5
|
+
|
|
6
|
+
from attrs import define, field
|
|
7
|
+
from src.types.common import UNSET, Unset
|
|
8
|
+
from src.types.core_item import HiveCoreItem
|
|
9
|
+
from src.types.enums.exercise_patbas_enum import PatbasEnum
|
|
10
|
+
from src.types.enums.exercise_preview_types import ExercisePreviewTypes
|
|
11
|
+
from src.types.enums.sync_status_enum import SyncStatusEnum
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from client import HiveClient
|
|
15
|
+
from src.types.module import Module
|
|
16
|
+
from src.types.subject import Subject
|
|
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: Mapping[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
|
|
@@ -0,0 +1,149 @@
|
|
|
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 as _attrs_define
|
|
11
|
+
from attrs import field
|
|
12
|
+
from src.types.common import UNSET, Unset
|
|
13
|
+
from src.types.core_item import HiveCoreItem
|
|
14
|
+
from src.types.enums.form_field_type_enum import FormFieldTypeEnum
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from client import HiveClient
|
|
18
|
+
from src.types.program import Class
|
|
19
|
+
|
|
20
|
+
T = TypeVar("T", bound="FormField")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@_attrs_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
|