"""The module that defines the ``Restriction`` model.
SPDX-License-Identifier: AGPL-3.0-only OR BSD-3-Clause-Clear
"""
from __future__ import annotations
import typing as t
from dataclasses import dataclass, field
import cg_request_args as rqa
from .. import parsers
from ..utils import to_dict
from .exam_environment_management import ExamEnvironmentManagement
from .restriction_exam_environment import RestrictionExamEnvironment
from .restriction_mixin import RestrictionMixin
from .restriction_not_set_session_lockdown import (
RestrictionNotSetSessionLockdown,
)
from .restriction_set_session_lockdown_with_entry_window import (
RestrictionSetSessionLockdownWithEntryWindow,
)
[docs]
@dataclass(kw_only=True)
class Restriction(RestrictionMixin):
"""The JSON representation of a Restriction."""
#: The unique identifier for this restriction.
id: str
#: Session lockdown settings, or not-set if disabled. When set, the
#: `entry_window` it carries is always the global configured window.
session_lockdown: t.Union[
RestrictionSetSessionLockdownWithEntryWindow,
RestrictionNotSetSessionLockdown,
]
#: What the viewer must do before they can enter, derived from the attached
#: exam environment provider's capabilities so this field and the
#: capability cannot drift. `not-set` when the exam is not proctored, and
#: for an anonymous viewer, who is told nothing.
exam_environment: RestrictionExamEnvironment
#: What the management UI needs to configure the exam environment: the
#: attached provider and the ones this tenant may attach, each described
#: through its capabilities. Distinct from the student-facing
#: `exam_environment` field. `None` — telling the viewer nothing — unless
#: the tenant's release flag is on and the viewer may manage exam
#: environments.
exam_environment_management: t.Optional[ExamEnvironmentManagement]
raw_data: t.Optional[t.Dict[str, t.Any]] = field(init=False, repr=False)
data_parser: t.ClassVar[t.Any] = rqa.Lazy(
lambda: RestrictionMixin.data_parser.parser.combine(
rqa.FixedMapping(
rqa.RequiredArgument(
"id",
rqa.SimpleValue.str,
doc="The unique identifier for this restriction.",
),
rqa.RequiredArgument(
"session_lockdown",
parsers.make_union(
parsers.ParserFor.make(
RestrictionSetSessionLockdownWithEntryWindow
),
parsers.ParserFor.make(
RestrictionNotSetSessionLockdown
),
),
doc="Session lockdown settings, or not-set if disabled. When set, the `entry_window` it carries is always the global configured window.",
),
rqa.RequiredArgument(
"exam_environment",
parsers.ParserFor.make(RestrictionExamEnvironment),
doc="What the viewer must do before they can enter, derived from the attached exam environment provider's capabilities so this field and the capability cannot drift. `not-set` when the exam is not proctored, and for an anonymous viewer, who is told nothing.",
),
rqa.RequiredArgument(
"exam_environment_management",
rqa.Nullable(
parsers.ParserFor.make(ExamEnvironmentManagement)
),
doc="What the management UI needs to configure the exam environment: the attached provider and the ones this tenant may attach, each described through its capabilities. Distinct from the student-facing `exam_environment` field. `None` — telling the viewer nothing — unless the tenant's release flag is on and the viewer may manage exam environments.",
),
)
)
)
def to_dict(self) -> t.Dict[str, t.Any]:
res: t.Dict[str, t.Any] = {
"id": to_dict(self.id),
"session_lockdown": to_dict(self.session_lockdown),
"exam_environment": to_dict(self.exam_environment),
"exam_environment_management": to_dict(
self.exam_environment_management
),
"password": to_dict(self.password),
}
return res
@classmethod
def from_dict(
cls: t.Type[Restriction], d: t.Dict[str, t.Any]
) -> Restriction:
parsed = cls.data_parser.try_parse(d)
res = cls(
id=parsed.id,
session_lockdown=parsed.session_lockdown,
exam_environment=parsed.exam_environment,
exam_environment_management=parsed.exam_environment_management,
password=parsed.password,
)
res.raw_data = d
return res
import os
if os.getenv("CG_GENERATING_DOCS", "False").lower() in ("", "true"):
from .restriction_mixin_not_set_password import (
RestrictionMixinNotSetPassword,
)
from .restriction_mixin_set_password import RestrictionMixinSetPassword