diff --git a/pylti1p3/grade.py b/pylti1p3/grade.py index 0f387d2..06aa1d6 100644 --- a/pylti1p3/grade.py +++ b/pylti1p3/grade.py @@ -1,5 +1,6 @@ import json import typing as t +from .exception import LtiException if t.TYPE_CHECKING: T_SELF = t.TypeVar('T_SELF', bound='Grade') @@ -15,57 +16,107 @@ class Grade(object): _user_id = None # type: t.Optional[str] _extra_claims = None # type: t.Optional[EXTRA_CLAIMS] + def _validate_score(self, score_value): + # type: (T_SELF, t.Any) -> t.Optional[str] + if not isinstance(score_value, (int, float)): + return 'score must be integer or float' + if score_value < 0: + return 'score must be positive number (including 0)' + return None + def get_score_given(self): # type: () -> t.Optional[float] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#scoregiven-and-scoremaximum + """ return self._score_given def set_score_given(self, value): # type: (T_SELF, float) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#scoregiven-and-scoremaximum + """ + err_msg = self._validate_score(value) + if err_msg is not None: + raise LtiException('Invalid scoreGiven value: ' + err_msg) self._score_given = value return self def get_score_maximum(self): # type: () -> t.Optional[float] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#scoregiven-and-scoremaximum + """ return self._score_maximum def set_score_maximum(self, value): # type: (T_SELF, float) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#scoregiven-and-scoremaximum + """ + err_msg = self._validate_score(value) + if err_msg is not None: + raise LtiException('Invalid scoreMaximum value: ' + err_msg) self._score_maximum = value return self def get_activity_progress(self): # type: () -> t.Optional[str] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#activityprogress + """ return self._activity_progress def set_activity_progress(self, value): # type: (T_SELF, str) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#activityprogress + """ self._activity_progress = value return self def get_grading_progress(self): # type: () -> t.Optional[str] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#gradingprogress + """ return self._grading_progress def set_grading_progress(self, value): # type: (T_SELF, str) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#gradingprogress + """ self._grading_progress = value return self def get_timestamp(self): # type: () -> t.Optional[str] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#timestamp + """ return self._timestamp def set_timestamp(self, value): # type: (T_SELF, str) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#timestamp + """ self._timestamp = value return self def get_user_id(self): # type: () -> t.Optional[str] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#userid-0 + """ return self._user_id def set_user_id(self, value): # type: (T_SELF, str) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#userid-0 + """ self._user_id = value return self diff --git a/pylti1p3/lineitem.py b/pylti1p3/lineitem.py index 3539365..7123772 100644 --- a/pylti1p3/lineitem.py +++ b/pylti1p3/lineitem.py @@ -1,5 +1,6 @@ import json import typing as t +from .exception import LtiException if t.TYPE_CHECKING: T_SELF = t.TypeVar('T_SELF', bound='LineItem') @@ -37,55 +38,96 @@ def set_id(self, value): def get_label(self): # type: () -> t.Optional[str] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#label + """ return self._label def set_label(self, value): # type: (T_SELF, str) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#label + """ self._label = value return self def get_score_maximum(self): # type: () -> t.Optional[float] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#scoremaximum + """ return self._score_maximum def set_score_maximum(self, value): # type: (T_SELF, float) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#scoremaximum + """ + if not isinstance(value, (int, float)): + raise LtiException('Invalid scoreMaximum value: score must be integer or float') + if value <= 0: + raise LtiException('Invalid scoreMaximum value: score must be non null value, strictly greater than 0') + self._score_maximum = value return self def get_resource_id(self): # type: () -> t.Optional[str] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#tool-resource-identifier-resourceid + """ return self._resource_id def set_resource_id(self, value): # type: (T_SELF, str) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#tool-resource-identifier-resourceid + """ self._resource_id = value return self def get_tag(self): # type: () -> t.Optional[str] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#tag + """ return self._tag def set_tag(self, value): # type: (T_SELF, str) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#tag + """ self._tag = value return self def get_start_date_time(self): # type: () -> t.Optional[str] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#startdatetime + """ return self._start_date_time def set_start_date_time(self, value): # type: (T_SELF, str) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#startdatetime + """ self._start_date_time = value return self def get_end_date_time(self): # type: () -> t.Optional[str] + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#enddatetime + """ return self._end_date_time def set_end_date_time(self, value): # type: (T_SELF, str) -> T_SELF + """ + https://www.imsglobal.org/spec/lti-ags/v2p0/#enddatetime + """ self._end_date_time = value return self @@ -93,7 +135,7 @@ def get_value(self): # type: () -> str data = { 'id': self._id if self._id else None, - 'scoreMaximum': self._score_maximum if self._score_maximum else None, + 'scoreMaximum': self._score_maximum, 'label': self._label, 'resourceId': self._resource_id, 'tag': self._tag,