From a6bbecd23a682158fa1d7defffc02bda2e2f6c48 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Tue, 19 Sep 2023 10:43:32 -0400 Subject: [PATCH 01/30] feat: add/remove course staff role events --- openedx_events/learning/data.py | 13 +++++++++++++ openedx_events/learning/signals.py | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 7e5d2f26..dcddc601 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -296,3 +296,16 @@ class ProgramCertificateData: status = attr.ib(type=str) url = attr.ib(type=str) certificate_available_date = attr.ib(type=datetime, default=None) + + +attr.s(frozen=True) +class CourseStaffData: + """ + Attributes defined for the Open edX Authentication function to Add Users to a role. + + Arguments: + course_key (Course ID): identifier of the course where the user will have staff role assigned/removed + user (UserData): User who will have the "Course Staff" role assigned/removed + """ + course_key = attr.ib(type=str) + user = attr.ib(UserData) diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index 5c139937..a8378612 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -13,6 +13,7 @@ CohortData, CourseDiscussionConfigurationData, CourseEnrollmentData, + CourseStaffData, PersistentCourseGradeData, ProgramCertificateData, UserData, @@ -196,3 +197,25 @@ "notification_data": UserNotificationData, } ) + +# .. event_type: org.openedx.learning.user.add.course.staff.role.v1 +# .. event_name: ADD_COURSE_STAFF_ROLE +# .. event_description: Assigns the "Course Staff" role to a user. +# .. event_data: CourseStaffData +ADD_COURSE_STAFF_ROLE = OpenEdxPublicSignal( + event_type="org.openedx.learning.user.add.course.staff.role.v1", + data={ + "course_staff_data": CourseStaffData, + } +) + +# .. event_type: org.openedx.learning.user.remove.course.staff.role.v1 +# .. event_name: REMOVE_COURSE_STAFF_ROLE +# .. event_description: Removes the "Course Staff" role from a user. +# .. event_data: CourseStaffData +REMOVE_COURSE_STAFF_ROLE = OpenEdxPublicSignal( + event_type="org.openedx.learning.user.remove.course.staff.role.v1", + data={ + "course_staff_data": CourseStaffData, + } +) From 7379a417da8670b0f5977ff10e131adb57c1efe8 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Tue, 19 Sep 2023 14:48:52 -0400 Subject: [PATCH 02/30] fix: generated avro schemas --- ...+user+add+course+staff+role+v1_schema.avsc | 59 +++++++++++++++++++ ...er+remove+course+staff+role+v1_schema.avsc | 59 +++++++++++++++++++ openedx_events/learning/data.py | 4 +- 3 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+add+course+staff+role+v1_schema.avsc create mode 100644 openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+remove+course+staff+role+v1_schema.avsc diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+add+course+staff+role+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+add+course+staff+role+v1_schema.avsc new file mode 100644 index 00000000..d3b16ea2 --- /dev/null +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+add+course+staff+role+v1_schema.avsc @@ -0,0 +1,59 @@ +{ + "name": "CloudEvent", + "type": "record", + "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", + "fields": [ + { + "name": "course_staff_data", + "type": { + "name": "CourseStaffData", + "type": "record", + "fields": [ + { + "name": "course_key", + "type": "string" + }, + { + "name": "user", + "type": { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } + } + ] + } + } + ], + "namespace": "org.openedx.learning.user.add.course.staff.role.v1" +} \ No newline at end of file diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+remove+course+staff+role+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+remove+course+staff+role+v1_schema.avsc new file mode 100644 index 00000000..bdb0c840 --- /dev/null +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+remove+course+staff+role+v1_schema.avsc @@ -0,0 +1,59 @@ +{ + "name": "CloudEvent", + "type": "record", + "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", + "fields": [ + { + "name": "course_staff_data", + "type": { + "name": "CourseStaffData", + "type": "record", + "fields": [ + { + "name": "course_key", + "type": "string" + }, + { + "name": "user", + "type": { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } + } + ] + } + } + ], + "namespace": "org.openedx.learning.user.remove.course.staff.role.v1" +} \ No newline at end of file diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index dcddc601..9c885e71 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -298,7 +298,7 @@ class ProgramCertificateData: certificate_available_date = attr.ib(type=datetime, default=None) -attr.s(frozen=True) +@attr.s(frozen=True) class CourseStaffData: """ Attributes defined for the Open edX Authentication function to Add Users to a role. @@ -308,4 +308,4 @@ class CourseStaffData: user (UserData): User who will have the "Course Staff" role assigned/removed """ course_key = attr.ib(type=str) - user = attr.ib(UserData) + user = attr.ib(type=UserData) From 0084f1374e7f2572060d3d89488051b99f8d82ae Mon Sep 17 00:00:00 2001 From: ilee2u Date: Tue, 19 Sep 2023 14:53:57 -0400 Subject: [PATCH 03/30] fix: quality --- openedx_events/learning/data.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 9c885e71..0493b3fb 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -307,5 +307,6 @@ class CourseStaffData: course_key (Course ID): identifier of the course where the user will have staff role assigned/removed user (UserData): User who will have the "Course Staff" role assigned/removed """ + course_key = attr.ib(type=str) user = attr.ib(type=UserData) From d3fe305698f50f529f241bba69fed6e55100694e Mon Sep 17 00:00:00 2001 From: ilee2u Date: Tue, 19 Sep 2023 16:07:36 -0400 Subject: [PATCH 04/30] feat: fixed language of signal --- openedx_events/learning/signals.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index a8378612..51fac1f6 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -198,23 +198,23 @@ } ) -# .. event_type: org.openedx.learning.user.add.course.staff.role.v1 -# .. event_name: ADD_COURSE_STAFF_ROLE -# .. event_description: Assigns the "Course Staff" role to a user. +# .. event_type: org.openedx.learning.user.course.staff.role.added.v1 +# .. event_name: COURSE_STAFF_ROLE_ADDED +# .. event_description: Adds the "Course Staff" role to a user. # .. event_data: CourseStaffData -ADD_COURSE_STAFF_ROLE = OpenEdxPublicSignal( - event_type="org.openedx.learning.user.add.course.staff.role.v1", +COURSE_STAFF_ROLE_ADDED = OpenEdxPublicSignal( + event_type="org.openedx.learning.user.course.staff.role.added.v1", data={ "course_staff_data": CourseStaffData, } ) -# .. event_type: org.openedx.learning.user.remove.course.staff.role.v1 -# .. event_name: REMOVE_COURSE_STAFF_ROLE +# .. event_type: org.openedx.learning.user.course.staff.role.removed.v1 +# .. event_name: COURSE_STAFF_ROLE_REMOVED # .. event_description: Removes the "Course Staff" role from a user. # .. event_data: CourseStaffData -REMOVE_COURSE_STAFF_ROLE = OpenEdxPublicSignal( - event_type="org.openedx.learning.user.remove.course.staff.role.v1", +COURSE_STAFF_ROLE_REMOVED = OpenEdxPublicSignal( + event_type="org.openedx.learning.user.course.staff.role.removed.v1", data={ "course_staff_data": CourseStaffData, } From 382ca93efcec1b5fd5ec9728dce8b1a66a48151b Mon Sep 17 00:00:00 2001 From: ilee2u Date: Tue, 19 Sep 2023 16:11:29 -0400 Subject: [PATCH 05/30] fix: avro. --- ...penedx+learning+user+course+staff+role+added+v1_schema.avsc} | 2 +- ...nedx+learning+user+course+staff+role+removed+v1_schema.avsc} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename openedx_events/event_bus/avro/tests/schemas/{org+openedx+learning+user+add+course+staff+role+v1_schema.avsc => org+openedx+learning+user+course+staff+role+added+v1_schema.avsc} (95%) rename openedx_events/event_bus/avro/tests/schemas/{org+openedx+learning+user+remove+course+staff+role+v1_schema.avsc => org+openedx+learning+user+course+staff+role+removed+v1_schema.avsc} (95%) diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+add+course+staff+role+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+course+staff+role+added+v1_schema.avsc similarity index 95% rename from openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+add+course+staff+role+v1_schema.avsc rename to openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+course+staff+role+added+v1_schema.avsc index d3b16ea2..b683d683 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+add+course+staff+role+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+course+staff+role+added+v1_schema.avsc @@ -55,5 +55,5 @@ } } ], - "namespace": "org.openedx.learning.user.add.course.staff.role.v1" + "namespace": "org.openedx.learning.user.course.staff.role.added.v1" } \ No newline at end of file diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+remove+course+staff+role+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+course+staff+role+removed+v1_schema.avsc similarity index 95% rename from openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+remove+course+staff+role+v1_schema.avsc rename to openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+course+staff+role+removed+v1_schema.avsc index bdb0c840..6b6f9dfa 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+remove+course+staff+role+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+user+course+staff+role+removed+v1_schema.avsc @@ -55,5 +55,5 @@ } } ], - "namespace": "org.openedx.learning.user.remove.course.staff.role.v1" + "namespace": "org.openedx.learning.user.course.staff.role.removed.v1" } \ No newline at end of file From ef56279158ec0c4a74be362f98f3d18b0c5451db Mon Sep 17 00:00:00 2001 From: ilee2u Date: Wed, 20 Sep 2023 09:47:29 -0400 Subject: [PATCH 06/30] fix: corrected signal descriptions --- openedx_events/learning/signals.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index 51fac1f6..c01bed66 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -200,7 +200,7 @@ # .. event_type: org.openedx.learning.user.course.staff.role.added.v1 # .. event_name: COURSE_STAFF_ROLE_ADDED -# .. event_description: Adds the "Course Staff" role to a user. +# .. event_description: Emitted when the "Course Staff" role is added to a user. # .. event_data: CourseStaffData COURSE_STAFF_ROLE_ADDED = OpenEdxPublicSignal( event_type="org.openedx.learning.user.course.staff.role.added.v1", @@ -211,7 +211,7 @@ # .. event_type: org.openedx.learning.user.course.staff.role.removed.v1 # .. event_name: COURSE_STAFF_ROLE_REMOVED -# .. event_description: Removes the "Course Staff" role from a user. +# .. event_description: Emitted when the "Course Staff" role is removed from a user. # .. event_data: CourseStaffData COURSE_STAFF_ROLE_REMOVED = OpenEdxPublicSignal( event_type="org.openedx.learning.user.course.staff.role.removed.v1", From f99c3b3fd312e624b17fb892ea06101a0b739a06 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Tue, 19 Sep 2023 16:05:24 -0400 Subject: [PATCH 07/30] feat: signals complete --- openedx_events/learning/data.py | 118 ++++++++++++++++++++++++++++- openedx_events/learning/signals.py | 70 +++++++++++++++++ 2 files changed, 186 insertions(+), 2 deletions(-) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 0493b3fb..4de822db 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -97,9 +97,10 @@ class CourseEnrollmentData: @attr.s(frozen=True) -class CertificateData: +class Invalidate: """ - Attributes defined for Open edX Certificate data object. + Attributes dAttributes for + This is separate from ceritificate data because of how diff the params areefined for Open edX Certificate data object. Arguments: user (UserData): user associated with the Certificate. @@ -310,3 +311,116 @@ class CourseStaffData: course_key = attr.ib(type=str) user = attr.ib(type=UserData) + + +attr.s(frozen=True) +class GradeOverrideData: + """ + Attributes defined for the Open edX Grades Override data object. + + user_id (int): identifier of the user to which the grade override belongs + course_key_or_id (str): identifier of the course to which the grade override belongs + usage_key_or_id (str): identifier of the content that will get a grade override + earned_all (float): the value that the subsection grade will be changed to + earned_graded (float): the value that the subsection grade will be changed to + overrider (str): the user creating the override + comment (str): reason for the override + """ + used_id = attr.ib(type=int) + course_key_or_id = attr.ib(type=str) + usage_key_or_id = attr.ib(type=str) + earned_all = attr.ib(type=float, default=None) + earned_graded = attr.ib(type=float, default=None) + overrider = attr.ib(type=str, default=None) + comment = attr.ib(type=str, default=None) + + +attr.s(frozen=True) +class InstructorCompletionData: + # TODO: These docstrings!!! + """ + Attributes defined for the + """ + username = attr.ib(type=str) + content_id = attr.ib(type=str) + course_id = attr.ib(type=str, default=None) + requesting_user = attr.ib(type=UserData, default=None) + + +attr.s(frozen=True) +class CreditRequirementStatusData: + """ + + """ + user_id = attr.id(type=int) + course_key_or_id = attr.id(type=str) + req_namespace = attr.id(type=str) + req_name = attr.id(type=str) + status = attr.id(type=str, default=None) + + +attr.s(frozen=True) +class InvalidateCertificateData: + """ + Attributes for + This is separate from ceritificate data because of how diff the params are + """ + user_id = attr.id(type=int) + course_id = attr.ib(type=str) +>>>>>>> 216b643 (feat: signals complete) + + +attr.s(frozen=True) +class GradeOverrideData: + """ + Attributes defined for the Open edX Grades Override data object. + + user_id (int): identifier of the user to which the grade override belongs + course_key_or_id (str): identifier of the course to which the grade override belongs + usage_key_or_id (str): identifier of the content that will get a grade override + earned_all (float): the value that the subsection grade will be changed to + earned_graded (float): the value that the subsection grade will be changed to + overrider (str): the user creating the override + comment (str): reason for the override + """ + used_id = attr.ib(type=int) + course_key_or_id = attr.ib(type=str) + usage_key_or_id = attr.ib(type=str) + earned_all = attr.ib(type=float, default=None) + earned_graded = attr.ib(type=float, default=None) + overrider = attr.ib(type=str, default=None) + comment = attr.ib(type=str, default=None) + + +attr.s(frozen=True) +class InstructorCompletionData: + # TODO: These docstrings!!! + """ + Attributes defined for the + """ + username = attr.ib(type=str) + content_id = attr.ib(type=str) + course_id = attr.ib(type=str, default=None) + requesting_user = attr.ib(type=UserData, default=None) + + +attr.s(frozen=True) +class CreditRequirementStatusData: + """ + + """ + user_id = attr.id(type=int) + course_key_or_id = attr.id(type=str) + req_namespace = attr.id(type=str) + req_name = attr.id(type=str) + status = attr.id(type=str, default=None) + + +attr.s(frozen=True) +class InvalidateCertificateData: + """ + Attributes for + This is separate from ceritificate data because of how diff the params are + """ + user_id = attr.id(type=int) + course_id = attr.ib(type=str) diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index c01bed66..b462ac58 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -14,6 +14,10 @@ CourseDiscussionConfigurationData, CourseEnrollmentData, CourseStaffData, + CreditRequirementStatusData, + GradeOverrideData, + InstructorCompletionData, + InvalidateCertificateData, PersistentCourseGradeData, ProgramCertificateData, UserData, @@ -219,3 +223,69 @@ "course_staff_data": CourseStaffData, } ) + +# .. event_type: org.openedx.learning.grade.override.created.v1 +# .. event_name: GRADE_OVERRIDE_CREATED +# .. event_description: Emitted when a user's grade for a subsection is overriden. +# .. event_data: GradeOverrideData +GRADE_OVERRIDE_CREATED = OpenEdxPublicSignal( + event_type="org.openedx.learning.grade.override.created.v1", + data={ + "grade_override_data": GradeOverrideData, + } +) + +# .. event_type: org.openedx.learning.grade.override.deleted.v1 +# .. event_name: GRADE_OVERRIDE_DELETED +# .. event_description: Emitted to undo a grade override for a subsection. +# .. event_data: GradeOverrideData +GRADE_OVERRIDE_DELETED = OpenEdxPublicSignal( + event_type="org.openedx.learning.grade.override.deleted.v1", + data={ + "grade_override_data": GradeOverrideData, + } +) + +# .. event_type: org.openedx.learning.all.child.xblocks.completed.v1 +# .. event_name: ALL_CHILD_XBLOCKS_COMPLETED +# .. event_description: Emitted to mark all the child xblocks of section/subsection/unit as completed. +# .. event_data: InstructorCompletionData +ALL_CHILD_XBLOCKS_COMPLETED = OpenEdxPublicSignal( + event_type="org.openedx.learning.all.child.xblocks.completed.v1", + data={ + "instructor_completed_data": InstructorCompletionData, + } +) + +# .. event_type: org.openedx.learning.all.child.xblocks.reset.v1 +# .. event_name: ALL_CHILD_XBLOCKS_RESET +# .. event_description: Emitted to reset the state of all child xblocks in a section/subsection/unit. +# .. event_data: InstructorCompletionData +ALL_CHILD_XBLOCKS_RESET = OpenEdxPublicSignal( + event_type="org.openedx.learning.all.child.xblocks.reset.v1", + data={ + "instructor_completed_data": InstructorCompletionData, + } +) + +# .. event_type: org.openedx.learning.credit.requirement.status.set.v1 +# .. event_name: CREDIT_REQUIREMENT_STATUS_SET +# .. event_description: Creates or modifies a user's credit requirement status for a course. +# .. event_data: CreditRequirementStatusData +CREDIT_REQUIREMENT_STATUS_SET = OpenEdxPublicSignal( + event_type="org.openedx.learning.set.credit.requirement.status.set.v1", + data={ + "credit_requirement_status_data": CreditRequirementStatusData, + } +) + +# .. event_type: org.openedx.learning.credit.requirement.status.data.v1 +# .. event_name: CREDIT_REQUIREMENT_STATUS_REMOVED +# .. event_description: Deletes a user's credit requirement status for a course. +# .. event_data: CreditRequirementStatusData +CREDIT_REQUIREMENT_STATUS_REMOVED = OpenEdxPublicSignal( + event_type="org.openedx.learning.remove.credit.requirement.status.v1", + data={ + "credit_requirement_status_data": CreditRequirementStatusData, + } +) From 8e858faa0283bc8e335134d4d8efe6d7093b65c3 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Tue, 19 Sep 2023 17:02:42 -0400 Subject: [PATCH 08/30] feat: improved docstrings pt 1 --- openedx_events/learning/data.py | 78 ++++++--------------------------- 1 file changed, 14 insertions(+), 64 deletions(-) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 4de822db..91ff052c 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -318,13 +318,14 @@ class GradeOverrideData: """ Attributes defined for the Open edX Grades Override data object. - user_id (int): identifier of the user to which the grade override belongs - course_key_or_id (str): identifier of the course to which the grade override belongs - usage_key_or_id (str): identifier of the content that will get a grade override - earned_all (float): the value that the subsection grade will be changed to - earned_graded (float): the value that the subsection grade will be changed to - overrider (str): the user creating the override - comment (str): reason for the override + Arguments: + user_id (int): identifier of the user to which the grade override belongs + course_key_or_id (str): identifier of the course to which the grade override belongs + usage_key_or_id (str): identifier of the content that will get a grade override + earned_all (float): the value that the subsection grade will be changed to + earned_graded (float): the value that the subsection grade will be changed to + overrider (str): the user creating the override + comment (str): reason for the override """ used_id = attr.ib(type=int) course_key_or_id = attr.ib(type=str) @@ -339,64 +340,13 @@ class GradeOverrideData: class InstructorCompletionData: # TODO: These docstrings!!! """ - Attributes defined for the - """ - username = attr.ib(type=str) - content_id = attr.ib(type=str) - course_id = attr.ib(type=str, default=None) - requesting_user = attr.ib(type=UserData, default=None) - + Attributes defined for Open edX Instructor service functions + that handle the completion state of xblocks within a course. -attr.s(frozen=True) -class CreditRequirementStatusData: - """ - - """ - user_id = attr.id(type=int) - course_key_or_id = attr.id(type=str) - req_namespace = attr.id(type=str) - req_name = attr.id(type=str) - status = attr.id(type=str, default=None) - - -attr.s(frozen=True) -class InvalidateCertificateData: - """ - Attributes for - This is separate from ceritificate data because of how diff the params are - """ - user_id = attr.id(type=int) - course_id = attr.ib(type=str) ->>>>>>> 216b643 (feat: signals complete) - - -attr.s(frozen=True) -class GradeOverrideData: - """ - Attributes defined for the Open edX Grades Override data object. - - user_id (int): identifier of the user to which the grade override belongs - course_key_or_id (str): identifier of the course to which the grade override belongs - usage_key_or_id (str): identifier of the content that will get a grade override - earned_all (float): the value that the subsection grade will be changed to - earned_graded (float): the value that the subsection grade will be changed to - overrider (str): the user creating the override - comment (str): reason for the override - """ - used_id = attr.ib(type=int) - course_key_or_id = attr.ib(type=str) - usage_key_or_id = attr.ib(type=str) - earned_all = attr.ib(type=float, default=None) - earned_graded = attr.ib(type=float, default=None) - overrider = attr.ib(type=str, default=None) - comment = attr.ib(type=str, default=None) - - -attr.s(frozen=True) -class InstructorCompletionData: - # TODO: These docstrings!!! - """ - Attributes defined for the + Arguments: + username (str): + content_id (str): + course_id (str): """ username = attr.ib(type=str) content_id = attr.ib(type=str) From e39f330741594d63ad824f9ca539e347d4cdfb5f Mon Sep 17 00:00:00 2001 From: ilee2u Date: Thu, 21 Sep 2023 11:39:59 -0400 Subject: [PATCH 09/30] feat: improved event defs + avro --- ...arning+exam+attempt+errored+v1_schema.avsc | 79 +++++++++++++++++ ...rning+exam+attempt+rejected+v1_schema.avsc | 79 +++++++++++++++++ ...learning+exam+attempt+reset+v1_schema.avsc | 79 +++++++++++++++++ ...ning+exam+attempt+submitted+v1_schema.avsc | 79 +++++++++++++++++ ...rning+exam+attempt+verified+v1_schema.avsc | 79 +++++++++++++++++ openedx_events/learning/data.py | 70 +++------------ openedx_events/learning/signals.py | 86 ++++++++----------- 7 files changed, 444 insertions(+), 107 deletions(-) create mode 100644 openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc create mode 100644 openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc create mode 100644 openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc create mode 100644 openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc create mode 100644 openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc new file mode 100644 index 00000000..bfbdb12d --- /dev/null +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc @@ -0,0 +1,79 @@ +{ + "name": "CloudEvent", + "type": "record", + "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", + "fields": [ + { + "name": "exam_attempt_data", + "type": { + "name": "ExamAttemptData", + "type": "record", + "fields": [ + { + "name": "user_id", + "type": "long" + }, + { + "name": "course_key", + "type": "string" + }, + { + "name": "usage_key", + "type": "string" + }, + { + "name": "requesting_user", + "type": [ + "null", + { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } + ], + "default": null + }, + { + "name": "credit_requirement_status", + "type": [ + "null", + "string" + ], + "default": null + } + ] + } + } + ], + "namespace": "org.openedx.learning.exam.attempt.errored.v1" +} \ No newline at end of file diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc new file mode 100644 index 00000000..dee79ecf --- /dev/null +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc @@ -0,0 +1,79 @@ +{ + "name": "CloudEvent", + "type": "record", + "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", + "fields": [ + { + "name": "exam_attempt_data", + "type": { + "name": "ExamAttemptData", + "type": "record", + "fields": [ + { + "name": "user_id", + "type": "long" + }, + { + "name": "course_key", + "type": "string" + }, + { + "name": "usage_key", + "type": "string" + }, + { + "name": "requesting_user", + "type": [ + "null", + { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } + ], + "default": null + }, + { + "name": "credit_requirement_status", + "type": [ + "null", + "string" + ], + "default": null + } + ] + } + } + ], + "namespace": "org.openedx.learning.exam.attempt.rejected.v1" +} \ No newline at end of file diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc new file mode 100644 index 00000000..a279d550 --- /dev/null +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc @@ -0,0 +1,79 @@ +{ + "name": "CloudEvent", + "type": "record", + "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", + "fields": [ + { + "name": "exam_attempt_data", + "type": { + "name": "ExamAttemptData", + "type": "record", + "fields": [ + { + "name": "user_id", + "type": "long" + }, + { + "name": "course_key", + "type": "string" + }, + { + "name": "usage_key", + "type": "string" + }, + { + "name": "requesting_user", + "type": [ + "null", + { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } + ], + "default": null + }, + { + "name": "credit_requirement_status", + "type": [ + "null", + "string" + ], + "default": null + } + ] + } + } + ], + "namespace": "org.openedx.learning.exam.attempt.reset.v1" +} \ No newline at end of file diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc new file mode 100644 index 00000000..dee651ad --- /dev/null +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc @@ -0,0 +1,79 @@ +{ + "name": "CloudEvent", + "type": "record", + "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", + "fields": [ + { + "name": "exam_attempt_data", + "type": { + "name": "ExamAttemptData", + "type": "record", + "fields": [ + { + "name": "user_id", + "type": "long" + }, + { + "name": "course_key", + "type": "string" + }, + { + "name": "usage_key", + "type": "string" + }, + { + "name": "requesting_user", + "type": [ + "null", + { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } + ], + "default": null + }, + { + "name": "credit_requirement_status", + "type": [ + "null", + "string" + ], + "default": null + } + ] + } + } + ], + "namespace": "org.openedx.learning.exam.attempt.submitted.v1" +} \ No newline at end of file diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc new file mode 100644 index 00000000..eeec0765 --- /dev/null +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc @@ -0,0 +1,79 @@ +{ + "name": "CloudEvent", + "type": "record", + "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", + "fields": [ + { + "name": "exam_attempt_data", + "type": { + "name": "ExamAttemptData", + "type": "record", + "fields": [ + { + "name": "user_id", + "type": "long" + }, + { + "name": "course_key", + "type": "string" + }, + { + "name": "usage_key", + "type": "string" + }, + { + "name": "requesting_user", + "type": [ + "null", + { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } + ], + "default": null + }, + { + "name": "credit_requirement_status", + "type": [ + "null", + "string" + ], + "default": null + } + ] + } + } + ], + "namespace": "org.openedx.learning.exam.attempt.verified.v1" +} \ No newline at end of file diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 91ff052c..6dc9668e 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -97,10 +97,9 @@ class CourseEnrollmentData: @attr.s(frozen=True) -class Invalidate: +class CertificateData: """ - Attributes dAttributes for - This is separate from ceritificate data because of how diff the params areefined for Open edX Certificate data object. + Attributes defined for Open edX Certificate data object. Arguments: user (UserData): user associated with the Certificate. @@ -313,64 +312,21 @@ class CourseStaffData: user = attr.ib(type=UserData) -attr.s(frozen=True) -class GradeOverrideData: +@attr.s(frozen=True) +class ExamAttemptData: """ - Attributes defined for the Open edX Grades Override data object. + Attributes defined for the Open edX Exam downstream effects. Arguments: user_id (int): identifier of the user to which the grade override belongs - course_key_or_id (str): identifier of the course to which the grade override belongs - usage_key_or_id (str): identifier of the content that will get a grade override - earned_all (float): the value that the subsection grade will be changed to - earned_graded (float): the value that the subsection grade will be changed to - overrider (str): the user creating the override - comment (str): reason for the override + course_key (CourseKey): identifier of the course to which the grade override belongs + usage_key (UsageKey): identifier of the content that will get a grade override + requesting_user (UserData): user triggering event, sent only when instructor modifies an exam attempt + credit_requirement_status (str): status to change the student's CreditRequirement to """ - used_id = attr.ib(type=int) - course_key_or_id = attr.ib(type=str) - usage_key_or_id = attr.ib(type=str) - earned_all = attr.ib(type=float, default=None) - earned_graded = attr.ib(type=float, default=None) - overrider = attr.ib(type=str, default=None) - comment = attr.ib(type=str, default=None) - -attr.s(frozen=True) -class InstructorCompletionData: - # TODO: These docstrings!!! - """ - Attributes defined for Open edX Instructor service functions - that handle the completion state of xblocks within a course. - - Arguments: - username (str): - content_id (str): - course_id (str): - """ - username = attr.ib(type=str) - content_id = attr.ib(type=str) - course_id = attr.ib(type=str, default=None) + user_id = attr.ib(type=int) + course_key = attr.ib(type=CourseKey) + usage_key = attr.ib(type=UsageKey) requesting_user = attr.ib(type=UserData, default=None) - - -attr.s(frozen=True) -class CreditRequirementStatusData: - """ - - """ - user_id = attr.id(type=int) - course_key_or_id = attr.id(type=str) - req_namespace = attr.id(type=str) - req_name = attr.id(type=str) - status = attr.id(type=str, default=None) - - -attr.s(frozen=True) -class InvalidateCertificateData: - """ - Attributes for - This is separate from ceritificate data because of how diff the params are - """ - user_id = attr.id(type=int) - course_id = attr.ib(type=str) + credit_requirement_status = attr.ib(type=str, default=None) diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index b462ac58..9fac0696 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -14,10 +14,7 @@ CourseDiscussionConfigurationData, CourseEnrollmentData, CourseStaffData, - CreditRequirementStatusData, - GradeOverrideData, - InstructorCompletionData, - InvalidateCertificateData, + ExamAttemptData, PersistentCourseGradeData, ProgramCertificateData, UserData, @@ -224,68 +221,57 @@ } ) -# .. event_type: org.openedx.learning.grade.override.created.v1 -# .. event_name: GRADE_OVERRIDE_CREATED -# .. event_description: Emitted when a user's grade for a subsection is overriden. -# .. event_data: GradeOverrideData -GRADE_OVERRIDE_CREATED = OpenEdxPublicSignal( - event_type="org.openedx.learning.grade.override.created.v1", +# .. event_type: org.openedx.learning.exam.attempt.submitted.v1 +# .. event_name: EXAM_ATTEMPT_SUBMITTED +# .. event_description: Emitted when an exam attempt is submitted by a learner. +# .. event_data: ExamAttemptData +EXAM_ATTEMPT_SUBMITTED = OpenEdxPublicSignal( + event_type="org.openedx.learning.exam.attempt.submitted.v1", data={ - "grade_override_data": GradeOverrideData, + "exam_attempt_data": ExamAttemptData, } ) -# .. event_type: org.openedx.learning.grade.override.deleted.v1 -# .. event_name: GRADE_OVERRIDE_DELETED -# .. event_description: Emitted to undo a grade override for a subsection. -# .. event_data: GradeOverrideData -GRADE_OVERRIDE_DELETED = OpenEdxPublicSignal( - event_type="org.openedx.learning.grade.override.deleted.v1", +# .. event_type: org.openedx.learning.exam.attempt.rejected.v1 +# .. event_name: EXAM_ATTEMPT_REJECTED +# .. event_description: Emitted when an exam attempt is marked rejected by an instructor or staff. +# .. event_data: ExamAttemptData +EXAM_ATTEMPT_REJECTED = OpenEdxPublicSignal( + event_type="org.openedx.learning.exam.attempt.rejected.v1", data={ - "grade_override_data": GradeOverrideData, + "exam_attempt_data": ExamAttemptData, } ) -# .. event_type: org.openedx.learning.all.child.xblocks.completed.v1 -# .. event_name: ALL_CHILD_XBLOCKS_COMPLETED -# .. event_description: Emitted to mark all the child xblocks of section/subsection/unit as completed. -# .. event_data: InstructorCompletionData -ALL_CHILD_XBLOCKS_COMPLETED = OpenEdxPublicSignal( - event_type="org.openedx.learning.all.child.xblocks.completed.v1", +# .. event_type: org.openedx.learning.exam.attempt.verified.v1 +# .. event_name: EXAM_ATTEMPT_VERIFIED +# .. event_description: Emitted when an exam attempt is marked verified by an instructor or staff. +# .. event_data: ExamAttemptData +EXAM_ATTEMPT_VERIFIED = OpenEdxPublicSignal( + event_type="org.openedx.learning.exam.attempt.verified.v1", data={ - "instructor_completed_data": InstructorCompletionData, + "exam_attempt_data": ExamAttemptData, } ) -# .. event_type: org.openedx.learning.all.child.xblocks.reset.v1 -# .. event_name: ALL_CHILD_XBLOCKS_RESET -# .. event_description: Emitted to reset the state of all child xblocks in a section/subsection/unit. -# .. event_data: InstructorCompletionData -ALL_CHILD_XBLOCKS_RESET = OpenEdxPublicSignal( - event_type="org.openedx.learning.all.child.xblocks.reset.v1", +# .. event_type: org.openedx.learning.exam.attempt.errored.v1 +# .. event_name: EXAM_ATTEMPT_ERRORED +# .. event_description: Emitted when a learner's exam attempt errors out. +# .. event_data: ExamAttemptData +EXAM_ATTEMPT_ERRORED = OpenEdxPublicSignal( + event_type="org.openedx.learning.exam.attempt.errored.v1", data={ - "instructor_completed_data": InstructorCompletionData, + "exam_attempt_data": ExamAttemptData, } ) -# .. event_type: org.openedx.learning.credit.requirement.status.set.v1 -# .. event_name: CREDIT_REQUIREMENT_STATUS_SET -# .. event_description: Creates or modifies a user's credit requirement status for a course. -# .. event_data: CreditRequirementStatusData -CREDIT_REQUIREMENT_STATUS_SET = OpenEdxPublicSignal( - event_type="org.openedx.learning.set.credit.requirement.status.set.v1", +# .. event_type: org.openedx.learning.exam.attempt.reset.v1 +# .. event_name: EXAM_ATTEMPT_RESET +# .. event_description: Emitted when an exam attempt is reset by an instructor or staff. +# .. event_data: ExamAttemptData +EXAM_ATTEMPT_RESET = OpenEdxPublicSignal( + event_type="org.openedx.learning.exam.attempt.reset.v1", data={ - "credit_requirement_status_data": CreditRequirementStatusData, - } -) - -# .. event_type: org.openedx.learning.credit.requirement.status.data.v1 -# .. event_name: CREDIT_REQUIREMENT_STATUS_REMOVED -# .. event_description: Deletes a user's credit requirement status for a course. -# .. event_data: CreditRequirementStatusData -CREDIT_REQUIREMENT_STATUS_REMOVED = OpenEdxPublicSignal( - event_type="org.openedx.learning.remove.credit.requirement.status.v1", - data={ - "credit_requirement_status_data": CreditRequirementStatusData, + "exam_attempt_data": ExamAttemptData, } ) From 3ed95a513a11e0341294913fe5d80eacb5aed5e4 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Thu, 21 Sep 2023 11:53:28 -0400 Subject: [PATCH 10/30] fix: rebasing off main only --- openedx_events/learning/data.py | 14 -------------- openedx_events/learning/signals.py | 23 ----------------------- 2 files changed, 37 deletions(-) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 6dc9668e..160ee87b 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -298,20 +298,6 @@ class ProgramCertificateData: certificate_available_date = attr.ib(type=datetime, default=None) -@attr.s(frozen=True) -class CourseStaffData: - """ - Attributes defined for the Open edX Authentication function to Add Users to a role. - - Arguments: - course_key (Course ID): identifier of the course where the user will have staff role assigned/removed - user (UserData): User who will have the "Course Staff" role assigned/removed - """ - - course_key = attr.ib(type=str) - user = attr.ib(type=UserData) - - @attr.s(frozen=True) class ExamAttemptData: """ diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index 9fac0696..b1dad70e 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -13,7 +13,6 @@ CohortData, CourseDiscussionConfigurationData, CourseEnrollmentData, - CourseStaffData, ExamAttemptData, PersistentCourseGradeData, ProgramCertificateData, @@ -199,28 +198,6 @@ } ) -# .. event_type: org.openedx.learning.user.course.staff.role.added.v1 -# .. event_name: COURSE_STAFF_ROLE_ADDED -# .. event_description: Emitted when the "Course Staff" role is added to a user. -# .. event_data: CourseStaffData -COURSE_STAFF_ROLE_ADDED = OpenEdxPublicSignal( - event_type="org.openedx.learning.user.course.staff.role.added.v1", - data={ - "course_staff_data": CourseStaffData, - } -) - -# .. event_type: org.openedx.learning.user.course.staff.role.removed.v1 -# .. event_name: COURSE_STAFF_ROLE_REMOVED -# .. event_description: Emitted when the "Course Staff" role is removed from a user. -# .. event_data: CourseStaffData -COURSE_STAFF_ROLE_REMOVED = OpenEdxPublicSignal( - event_type="org.openedx.learning.user.course.staff.role.removed.v1", - data={ - "course_staff_data": CourseStaffData, - } -) - # .. event_type: org.openedx.learning.exam.attempt.submitted.v1 # .. event_name: EXAM_ATTEMPT_SUBMITTED # .. event_description: Emitted when an exam attempt is submitted by a learner. From e148d0fa93979fee7e33c5152aa014478cc8e1b5 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Thu, 21 Sep 2023 14:12:12 -0400 Subject: [PATCH 11/30] fix: made signal purpose broader --- openedx_events/learning/signals.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index b1dad70e..3248faa2 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -211,7 +211,7 @@ # .. event_type: org.openedx.learning.exam.attempt.rejected.v1 # .. event_name: EXAM_ATTEMPT_REJECTED -# .. event_description: Emitted when an exam attempt is marked rejected by an instructor or staff. +# .. event_description: Emitted when an exam attempt is marked rejected. # .. event_data: ExamAttemptData EXAM_ATTEMPT_REJECTED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.rejected.v1", @@ -222,7 +222,7 @@ # .. event_type: org.openedx.learning.exam.attempt.verified.v1 # .. event_name: EXAM_ATTEMPT_VERIFIED -# .. event_description: Emitted when an exam attempt is marked verified by an instructor or staff. +# .. event_description: Emitted when an exam attempt is marked verified. # .. event_data: ExamAttemptData EXAM_ATTEMPT_VERIFIED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.verified.v1", @@ -244,7 +244,7 @@ # .. event_type: org.openedx.learning.exam.attempt.reset.v1 # .. event_name: EXAM_ATTEMPT_RESET -# .. event_description: Emitted when an exam attempt is reset by an instructor or staff. +# .. event_description: Emitted when an exam attempt is reset. # .. event_data: ExamAttemptData EXAM_ATTEMPT_RESET = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.reset.v1", From e61f72995c47bfa455d485a58988239dac20e7d1 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Thu, 21 Sep 2023 14:29:11 -0400 Subject: [PATCH 12/30] fix: removed unecessary event param - Also changed user_id to student_user --- openedx_events/learning/data.py | 13 ++++++------- openedx_events/learning/signals.py | 10 +++++----- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 160ee87b..ad9769a7 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -304,15 +304,14 @@ class ExamAttemptData: Attributes defined for the Open edX Exam downstream effects. Arguments: - user_id (int): identifier of the user to which the grade override belongs - course_key (CourseKey): identifier of the course to which the grade override belongs - usage_key (UsageKey): identifier of the content that will get a grade override - requesting_user (UserData): user triggering event, sent only when instructor modifies an exam attempt - credit_requirement_status (str): status to change the student's CreditRequirement to + student_user (UserData): User object for the student to whom the exam attempt belongs + course_key (CourseKey): identifier of the course to which the exam attempt belongs + usage_key (UsageKey): identifier of the content that will get a exam attempt + requesting_user (UserData): user triggering the event (sometimes a non-learner, e.g. an instructor) + credit_requirement_status (str): what to change the student's CreditRequirement status to """ - user_id = attr.ib(type=int) + student_user = attr.ib(type=UserData) course_key = attr.ib(type=CourseKey) usage_key = attr.ib(type=UsageKey) requesting_user = attr.ib(type=UserData, default=None) - credit_requirement_status = attr.ib(type=str, default=None) diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index 3248faa2..6ce99a56 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -205,7 +205,7 @@ EXAM_ATTEMPT_SUBMITTED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.submitted.v1", data={ - "exam_attempt_data": ExamAttemptData, + "exam_attempt": ExamAttemptData, } ) @@ -216,7 +216,7 @@ EXAM_ATTEMPT_REJECTED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.rejected.v1", data={ - "exam_attempt_data": ExamAttemptData, + "exam_attempt": ExamAttemptData, } ) @@ -227,7 +227,7 @@ EXAM_ATTEMPT_VERIFIED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.verified.v1", data={ - "exam_attempt_data": ExamAttemptData, + "exam_attempt": ExamAttemptData, } ) @@ -238,7 +238,7 @@ EXAM_ATTEMPT_ERRORED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.errored.v1", data={ - "exam_attempt_data": ExamAttemptData, + "exam_attempt": ExamAttemptData, } ) @@ -249,6 +249,6 @@ EXAM_ATTEMPT_RESET = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.reset.v1", data={ - "exam_attempt_data": ExamAttemptData, + "exam_attempt": ExamAttemptData, } ) From 0615aafa9a7730c389ab5c2ce26718a54ae99ee5 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Thu, 21 Sep 2023 14:31:43 -0400 Subject: [PATCH 13/30] fix: avro --- ...arning+exam+attempt+errored+v1_schema.avsc | 84 +++++++++---------- ...rning+exam+attempt+rejected+v1_schema.avsc | 84 +++++++++---------- ...learning+exam+attempt+reset+v1_schema.avsc | 84 +++++++++---------- ...ning+exam+attempt+submitted+v1_schema.avsc | 84 +++++++++---------- ...rning+exam+attempt+verified+v1_schema.avsc | 84 +++++++++---------- 5 files changed, 190 insertions(+), 230 deletions(-) diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc index bfbdb12d..367968ef 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc @@ -4,14 +4,48 @@ "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", "fields": [ { - "name": "exam_attempt_data", + "name": "exam_attempt", "type": { "name": "ExamAttemptData", "type": "record", "fields": [ { - "name": "user_id", - "type": "long" + "name": "student_user", + "type": { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } }, { "name": "course_key", @@ -25,49 +59,7 @@ "name": "requesting_user", "type": [ "null", - { - "name": "UserData", - "type": "record", - "fields": [ - { - "name": "id", - "type": "long" - }, - { - "name": "is_active", - "type": "boolean" - }, - { - "name": "pii", - "type": { - "name": "UserPersonalData", - "type": "record", - "fields": [ - { - "name": "username", - "type": "string" - }, - { - "name": "email", - "type": "string" - }, - { - "name": "name", - "type": "string" - } - ] - } - } - ] - } - ], - "default": null - }, - { - "name": "credit_requirement_status", - "type": [ - "null", - "string" + "UserData" ], "default": null } diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc index dee79ecf..4531a8b7 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc @@ -4,14 +4,48 @@ "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", "fields": [ { - "name": "exam_attempt_data", + "name": "exam_attempt", "type": { "name": "ExamAttemptData", "type": "record", "fields": [ { - "name": "user_id", - "type": "long" + "name": "student_user", + "type": { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } }, { "name": "course_key", @@ -25,49 +59,7 @@ "name": "requesting_user", "type": [ "null", - { - "name": "UserData", - "type": "record", - "fields": [ - { - "name": "id", - "type": "long" - }, - { - "name": "is_active", - "type": "boolean" - }, - { - "name": "pii", - "type": { - "name": "UserPersonalData", - "type": "record", - "fields": [ - { - "name": "username", - "type": "string" - }, - { - "name": "email", - "type": "string" - }, - { - "name": "name", - "type": "string" - } - ] - } - } - ] - } - ], - "default": null - }, - { - "name": "credit_requirement_status", - "type": [ - "null", - "string" + "UserData" ], "default": null } diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc index a279d550..ee2e96a9 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc @@ -4,14 +4,48 @@ "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", "fields": [ { - "name": "exam_attempt_data", + "name": "exam_attempt", "type": { "name": "ExamAttemptData", "type": "record", "fields": [ { - "name": "user_id", - "type": "long" + "name": "student_user", + "type": { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } }, { "name": "course_key", @@ -25,49 +59,7 @@ "name": "requesting_user", "type": [ "null", - { - "name": "UserData", - "type": "record", - "fields": [ - { - "name": "id", - "type": "long" - }, - { - "name": "is_active", - "type": "boolean" - }, - { - "name": "pii", - "type": { - "name": "UserPersonalData", - "type": "record", - "fields": [ - { - "name": "username", - "type": "string" - }, - { - "name": "email", - "type": "string" - }, - { - "name": "name", - "type": "string" - } - ] - } - } - ] - } - ], - "default": null - }, - { - "name": "credit_requirement_status", - "type": [ - "null", - "string" + "UserData" ], "default": null } diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc index dee651ad..772461bd 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc @@ -4,14 +4,48 @@ "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", "fields": [ { - "name": "exam_attempt_data", + "name": "exam_attempt", "type": { "name": "ExamAttemptData", "type": "record", "fields": [ { - "name": "user_id", - "type": "long" + "name": "student_user", + "type": { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } }, { "name": "course_key", @@ -25,49 +59,7 @@ "name": "requesting_user", "type": [ "null", - { - "name": "UserData", - "type": "record", - "fields": [ - { - "name": "id", - "type": "long" - }, - { - "name": "is_active", - "type": "boolean" - }, - { - "name": "pii", - "type": { - "name": "UserPersonalData", - "type": "record", - "fields": [ - { - "name": "username", - "type": "string" - }, - { - "name": "email", - "type": "string" - }, - { - "name": "name", - "type": "string" - } - ] - } - } - ] - } - ], - "default": null - }, - { - "name": "credit_requirement_status", - "type": [ - "null", - "string" + "UserData" ], "default": null } diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc index eeec0765..2cd6ef62 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc @@ -4,14 +4,48 @@ "doc": "Avro Event Format for CloudEvents created with openedx_events/schema", "fields": [ { - "name": "exam_attempt_data", + "name": "exam_attempt", "type": { "name": "ExamAttemptData", "type": "record", "fields": [ { - "name": "user_id", - "type": "long" + "name": "student_user", + "type": { + "name": "UserData", + "type": "record", + "fields": [ + { + "name": "id", + "type": "long" + }, + { + "name": "is_active", + "type": "boolean" + }, + { + "name": "pii", + "type": { + "name": "UserPersonalData", + "type": "record", + "fields": [ + { + "name": "username", + "type": "string" + }, + { + "name": "email", + "type": "string" + }, + { + "name": "name", + "type": "string" + } + ] + } + } + ] + } }, { "name": "course_key", @@ -25,49 +59,7 @@ "name": "requesting_user", "type": [ "null", - { - "name": "UserData", - "type": "record", - "fields": [ - { - "name": "id", - "type": "long" - }, - { - "name": "is_active", - "type": "boolean" - }, - { - "name": "pii", - "type": { - "name": "UserPersonalData", - "type": "record", - "fields": [ - { - "name": "username", - "type": "string" - }, - { - "name": "email", - "type": "string" - }, - { - "name": "name", - "type": "string" - } - ] - } - } - ] - } - ], - "default": null - }, - { - "name": "credit_requirement_status", - "type": [ - "null", - "string" + "UserData" ], "default": null } From 0f31223c013446f59a5abe72b28d694bf4f48943 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Thu, 21 Sep 2023 15:29:48 -0400 Subject: [PATCH 14/30] fix: removed unecessary docstring --- openedx_events/learning/data.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index ad9769a7..a9c81e77 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -304,11 +304,10 @@ class ExamAttemptData: Attributes defined for the Open edX Exam downstream effects. Arguments: - student_user (UserData): User object for the student to whom the exam attempt belongs + student_user (UserData): user object for the student to whom the exam attempt belongs course_key (CourseKey): identifier of the course to which the exam attempt belongs usage_key (UsageKey): identifier of the content that will get a exam attempt requesting_user (UserData): user triggering the event (sometimes a non-learner, e.g. an instructor) - credit_requirement_status (str): what to change the student's CreditRequirement status to """ student_user = attr.ib(type=UserData) From 2e3de7a4f4f048b9e75ff6b2d736d1ca31d4c814 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Thu, 21 Sep 2023 15:56:33 -0400 Subject: [PATCH 15/30] chore: version bump --- CHANGELOG.rst | 6 ++++++ openedx_events/__init__.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b833062d..4fcb8c43 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,12 @@ Changed ~~~~~~~ * Re-licensed this repository from AGPL 3.0 to Apache 2.0 +[8.670] - 2023-09-21 +-------------------- +Added +~~~~~ +* Added new ``EXAM_ATTEMPT_SUBMITTED``, ``EXAM_ATTEMPT_REJECTED``, ``EXAM_ATTEMPT_VERIFIED``, ``EXAM_ATTEMPT_RESET``, and ``EXAM_ATTEMPT_ERRORED`` in learning. + [8.6.0] - 2023-08-28 -------------------- Added diff --git a/openedx_events/__init__.py b/openedx_events/__init__.py index 3feb7fdf..e2ea442e 100644 --- a/openedx_events/__init__.py +++ b/openedx_events/__init__.py @@ -5,4 +5,4 @@ more information about the project. """ -__version__ = "8.6.0" +__version__ = "8.7.0" From 6a2647fac958f50b26ad9d1cad806d18f7fb8b06 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Fri, 22 Sep 2023 13:47:01 -0400 Subject: [PATCH 16/30] feat: added exam_type to ExamAttemptData --- openedx_events/learning/data.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index a9c81e77..4deae7cc 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -308,9 +308,11 @@ class ExamAttemptData: course_key (CourseKey): identifier of the course to which the exam attempt belongs usage_key (UsageKey): identifier of the content that will get a exam attempt requesting_user (UserData): user triggering the event (sometimes a non-learner, e.g. an instructor) + exam_type (str): type of exam that was taken (e.g. timed, proctored, etc.) """ student_user = attr.ib(type=UserData) course_key = attr.ib(type=CourseKey) usage_key = attr.ib(type=UsageKey) requesting_user = attr.ib(type=UserData, default=None) + exam_type = attr.id(type=str) From 121f6bacf37268ed1ef6497714e9cb2bd277ab79 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Wed, 27 Sep 2023 12:12:52 -0400 Subject: [PATCH 17/30] fix: corrected exam_type attr.ib --- .../org+openedx+learning+exam+attempt+errored+v1_schema.avsc | 4 ++++ .../org+openedx+learning+exam+attempt+rejected+v1_schema.avsc | 4 ++++ .../org+openedx+learning+exam+attempt+reset+v1_schema.avsc | 4 ++++ ...org+openedx+learning+exam+attempt+submitted+v1_schema.avsc | 4 ++++ .../org+openedx+learning+exam+attempt+verified+v1_schema.avsc | 4 ++++ openedx_events/learning/data.py | 2 +- 6 files changed, 21 insertions(+), 1 deletion(-) diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc index 367968ef..eb7c946f 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc @@ -55,6 +55,10 @@ "name": "usage_key", "type": "string" }, + { + "name": "exam_type", + "type": "string" + }, { "name": "requesting_user", "type": [ diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc index 4531a8b7..7d726e63 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc @@ -55,6 +55,10 @@ "name": "usage_key", "type": "string" }, + { + "name": "exam_type", + "type": "string" + }, { "name": "requesting_user", "type": [ diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc index ee2e96a9..c226aa0a 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc @@ -55,6 +55,10 @@ "name": "usage_key", "type": "string" }, + { + "name": "exam_type", + "type": "string" + }, { "name": "requesting_user", "type": [ diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc index 772461bd..286747b8 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc @@ -55,6 +55,10 @@ "name": "usage_key", "type": "string" }, + { + "name": "exam_type", + "type": "string" + }, { "name": "requesting_user", "type": [ diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc index 2cd6ef62..b6250c9c 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc @@ -55,6 +55,10 @@ "name": "usage_key", "type": "string" }, + { + "name": "exam_type", + "type": "string" + }, { "name": "requesting_user", "type": [ diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 4deae7cc..849816a0 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -314,5 +314,5 @@ class ExamAttemptData: student_user = attr.ib(type=UserData) course_key = attr.ib(type=CourseKey) usage_key = attr.ib(type=UsageKey) + exam_type = attr.ib(type=str) requesting_user = attr.ib(type=UserData, default=None) - exam_type = attr.id(type=str) From c3074b8ab9dc24d622dd60e7fc603039f13ce52e Mon Sep 17 00:00:00 2001 From: ilee2u Date: Thu, 28 Sep 2023 15:26:53 -0400 Subject: [PATCH 18/30] feat: Added "Special" to data name - Specified that the events are only emitted when special exams go through edx-exams. - Re-ordered params in data docstring --- openedx_events/learning/data.py | 10 ++++++++-- openedx_events/learning/signals.py | 32 +++++++++++++++--------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 849816a0..3edd3c45 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -299,16 +299,22 @@ class ProgramCertificateData: @attr.s(frozen=True) -class ExamAttemptData: +class SpecialExamAttemptData: """ Attributes defined for the Open edX Exam downstream effects. + Note that events that use this data type: + A. Pretain to "Special Exams", e.g. Timed or Proctored exams, and not non-timed course + subsections that are labelled as an exam. + B. Are only ever emitted from the newer exams backend, edx-exams, and never from the + legacy exams backend, edx-proctoring. + Arguments: student_user (UserData): user object for the student to whom the exam attempt belongs course_key (CourseKey): identifier of the course to which the exam attempt belongs usage_key (UsageKey): identifier of the content that will get a exam attempt - requesting_user (UserData): user triggering the event (sometimes a non-learner, e.g. an instructor) exam_type (str): type of exam that was taken (e.g. timed, proctored, etc.) + requesting_user (UserData): user triggering the event (sometimes a non-learner, e.g. an instructor) """ student_user = attr.ib(type=UserData) diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index 6ce99a56..afadb690 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -13,7 +13,7 @@ CohortData, CourseDiscussionConfigurationData, CourseEnrollmentData, - ExamAttemptData, + SpecialExamAttemptData, PersistentCourseGradeData, ProgramCertificateData, UserData, @@ -200,55 +200,55 @@ # .. event_type: org.openedx.learning.exam.attempt.submitted.v1 # .. event_name: EXAM_ATTEMPT_SUBMITTED -# .. event_description: Emitted when an exam attempt is submitted by a learner. -# .. event_data: ExamAttemptData +# .. event_description: Emitted when an exam attempt is submitted by a learner in edx-exams. +# .. event_data: SpecialExamAttemptData EXAM_ATTEMPT_SUBMITTED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.submitted.v1", data={ - "exam_attempt": ExamAttemptData, + "exam_attempt": SpecialExamAttemptData, } ) # .. event_type: org.openedx.learning.exam.attempt.rejected.v1 # .. event_name: EXAM_ATTEMPT_REJECTED -# .. event_description: Emitted when an exam attempt is marked rejected. -# .. event_data: ExamAttemptData +# .. event_description: Emitted when an exam attempt is marked rejected in edx-exams. +# .. event_data: SpecialExamAttemptData EXAM_ATTEMPT_REJECTED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.rejected.v1", data={ - "exam_attempt": ExamAttemptData, + "exam_attempt": SpecialExamAttemptData, } ) # .. event_type: org.openedx.learning.exam.attempt.verified.v1 # .. event_name: EXAM_ATTEMPT_VERIFIED -# .. event_description: Emitted when an exam attempt is marked verified. -# .. event_data: ExamAttemptData +# .. event_description: Emitted when an exam attempt is marked verified in edx-exams. +# .. event_data: SpecialExamAttemptData EXAM_ATTEMPT_VERIFIED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.verified.v1", data={ - "exam_attempt": ExamAttemptData, + "exam_attempt": SpecialExamAttemptData, } ) # .. event_type: org.openedx.learning.exam.attempt.errored.v1 # .. event_name: EXAM_ATTEMPT_ERRORED -# .. event_description: Emitted when a learner's exam attempt errors out. -# .. event_data: ExamAttemptData +# .. event_description: Emitted when a learner's exam attempt errors out in edx-exams. +# .. event_data: SpecialExamAttemptData EXAM_ATTEMPT_ERRORED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.errored.v1", data={ - "exam_attempt": ExamAttemptData, + "exam_attempt": SpecialExamAttemptData, } ) # .. event_type: org.openedx.learning.exam.attempt.reset.v1 # .. event_name: EXAM_ATTEMPT_RESET -# .. event_description: Emitted when an exam attempt is reset. -# .. event_data: ExamAttemptData +# .. event_description: Emitted when an exam attempt is reset in edx-exams. +# .. event_data: SpecialExamAttemptData EXAM_ATTEMPT_RESET = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.reset.v1", data={ - "exam_attempt": ExamAttemptData, + "exam_attempt": SpecialExamAttemptData, } ) From 8917946d01f2c928f8aeb6f10e182142650b1c18 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Thu, 28 Sep 2023 15:34:00 -0400 Subject: [PATCH 19/30] chore: avro --- .../org+openedx+learning+exam+attempt+errored+v1_schema.avsc | 2 +- .../org+openedx+learning+exam+attempt+rejected+v1_schema.avsc | 2 +- .../org+openedx+learning+exam+attempt+reset+v1_schema.avsc | 2 +- .../org+openedx+learning+exam+attempt+submitted+v1_schema.avsc | 2 +- .../org+openedx+learning+exam+attempt+verified+v1_schema.avsc | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc index eb7c946f..5381100e 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc @@ -6,7 +6,7 @@ { "name": "exam_attempt", "type": { - "name": "ExamAttemptData", + "name": "SpecialExamAttemptData", "type": "record", "fields": [ { diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc index 7d726e63..ab2fd4b5 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc @@ -6,7 +6,7 @@ { "name": "exam_attempt", "type": { - "name": "ExamAttemptData", + "name": "SpecialExamAttemptData", "type": "record", "fields": [ { diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc index c226aa0a..328231db 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc @@ -6,7 +6,7 @@ { "name": "exam_attempt", "type": { - "name": "ExamAttemptData", + "name": "SpecialExamAttemptData", "type": "record", "fields": [ { diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc index 286747b8..bc487554 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc @@ -6,7 +6,7 @@ { "name": "exam_attempt", "type": { - "name": "ExamAttemptData", + "name": "SpecialExamAttemptData", "type": "record", "fields": [ { diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc index b6250c9c..eaf00c4f 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc @@ -6,7 +6,7 @@ { "name": "exam_attempt", "type": { - "name": "ExamAttemptData", + "name": "SpecialExamAttemptData", "type": "record", "fields": [ { From d3dbf5ad00227ae0867aa682e90948a34d14f39f Mon Sep 17 00:00:00 2001 From: ilee2u Date: Thu, 28 Sep 2023 15:36:53 -0400 Subject: [PATCH 20/30] chore: move data import --- openedx_events/learning/signals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index afadb690..ceaeb393 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -13,9 +13,9 @@ CohortData, CourseDiscussionConfigurationData, CourseEnrollmentData, - SpecialExamAttemptData, PersistentCourseGradeData, ProgramCertificateData, + SpecialExamAttemptData, UserData, UserNotificationData, XBlockSkillVerificationData, From 2de9b4ae0f78399b3b7ebc3ed7b80171ab1dacb9 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Fri, 29 Sep 2023 09:34:01 -0400 Subject: [PATCH 21/30] chore: changelog correction --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4fcb8c43..85c4caf5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,7 +17,7 @@ Changed ~~~~~~~ * Re-licensed this repository from AGPL 3.0 to Apache 2.0 -[8.670] - 2023-09-21 +[8.70] - 2023-09-29 -------------------- Added ~~~~~ From d9f9e1b99b685ee3f4e554f0a10a9e37b5562b48 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Fri, 29 Sep 2023 10:23:56 -0400 Subject: [PATCH 22/30] chore: 8.70 -> 8.7.0 - I literally forgot a period oi --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 85c4caf5..c68c76b3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,7 +17,7 @@ Changed ~~~~~~~ * Re-licensed this repository from AGPL 3.0 to Apache 2.0 -[8.70] - 2023-09-29 +[8.7.0] - 2023-09-29 -------------------- Added ~~~~~ From 2a2299a0658320d05335129a85669a7edcfbaa0a Mon Sep 17 00:00:00 2001 From: ilee2u Date: Fri, 29 Sep 2023 11:21:28 -0400 Subject: [PATCH 23/30] docs: clarified signal name prefix EXAM_ --- openedx_events/learning/data.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 3edd3c45..290e0b41 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -309,6 +309,10 @@ class SpecialExamAttemptData: B. Are only ever emitted from the newer exams backend, edx-exams, and never from the legacy exams backend, edx-proctoring. + The event signals that use this data have the prefix `EXAM_`, which is equivalent to "special exam". + We are using this as a shortened form of the prefix `SPECIAL_EXAM` to avoid confusion, as these are likely + the only type of exams that will be of concern in the context of events/the event bus. + Arguments: student_user (UserData): user object for the student to whom the exam attempt belongs course_key (CourseKey): identifier of the course to which the exam attempt belongs From 918a6419b0e6473f6652adc5d275286d4b96c8c0 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Fri, 29 Sep 2023 13:48:27 -0400 Subject: [PATCH 24/30] feat: removed "Special" from data name --- ...arning+exam+attempt+errored+v1_schema.avsc | 2 +- ...rning+exam+attempt+rejected+v1_schema.avsc | 2 +- ...learning+exam+attempt+reset+v1_schema.avsc | 2 +- ...ning+exam+attempt+submitted+v1_schema.avsc | 2 +- ...rning+exam+attempt+verified+v1_schema.avsc | 2 +- openedx_events/learning/data.py | 2 +- openedx_events/learning/signals.py | 22 +++++++++---------- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc index 5381100e..eb7c946f 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+errored+v1_schema.avsc @@ -6,7 +6,7 @@ { "name": "exam_attempt", "type": { - "name": "SpecialExamAttemptData", + "name": "ExamAttemptData", "type": "record", "fields": [ { diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc index ab2fd4b5..7d726e63 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+rejected+v1_schema.avsc @@ -6,7 +6,7 @@ { "name": "exam_attempt", "type": { - "name": "SpecialExamAttemptData", + "name": "ExamAttemptData", "type": "record", "fields": [ { diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc index 328231db..c226aa0a 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+reset+v1_schema.avsc @@ -6,7 +6,7 @@ { "name": "exam_attempt", "type": { - "name": "SpecialExamAttemptData", + "name": "ExamAttemptData", "type": "record", "fields": [ { diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc index bc487554..286747b8 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+submitted+v1_schema.avsc @@ -6,7 +6,7 @@ { "name": "exam_attempt", "type": { - "name": "SpecialExamAttemptData", + "name": "ExamAttemptData", "type": "record", "fields": [ { diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc index eaf00c4f..b6250c9c 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+learning+exam+attempt+verified+v1_schema.avsc @@ -6,7 +6,7 @@ { "name": "exam_attempt", "type": { - "name": "SpecialExamAttemptData", + "name": "ExamAttemptData", "type": "record", "fields": [ { diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 290e0b41..b004cc60 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -299,7 +299,7 @@ class ProgramCertificateData: @attr.s(frozen=True) -class SpecialExamAttemptData: +class ExamAttemptData: """ Attributes defined for the Open edX Exam downstream effects. diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index ceaeb393..33e18084 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -15,7 +15,7 @@ CourseEnrollmentData, PersistentCourseGradeData, ProgramCertificateData, - SpecialExamAttemptData, + ExamAttemptData, UserData, UserNotificationData, XBlockSkillVerificationData, @@ -201,54 +201,54 @@ # .. event_type: org.openedx.learning.exam.attempt.submitted.v1 # .. event_name: EXAM_ATTEMPT_SUBMITTED # .. event_description: Emitted when an exam attempt is submitted by a learner in edx-exams. -# .. event_data: SpecialExamAttemptData +# .. event_data: ExamAttemptData EXAM_ATTEMPT_SUBMITTED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.submitted.v1", data={ - "exam_attempt": SpecialExamAttemptData, + "exam_attempt": ExamAttemptData, } ) # .. event_type: org.openedx.learning.exam.attempt.rejected.v1 # .. event_name: EXAM_ATTEMPT_REJECTED # .. event_description: Emitted when an exam attempt is marked rejected in edx-exams. -# .. event_data: SpecialExamAttemptData +# .. event_data: ExamAttemptData EXAM_ATTEMPT_REJECTED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.rejected.v1", data={ - "exam_attempt": SpecialExamAttemptData, + "exam_attempt": ExamAttemptData, } ) # .. event_type: org.openedx.learning.exam.attempt.verified.v1 # .. event_name: EXAM_ATTEMPT_VERIFIED # .. event_description: Emitted when an exam attempt is marked verified in edx-exams. -# .. event_data: SpecialExamAttemptData +# .. event_data: ExamAttemptData EXAM_ATTEMPT_VERIFIED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.verified.v1", data={ - "exam_attempt": SpecialExamAttemptData, + "exam_attempt": ExamAttemptData, } ) # .. event_type: org.openedx.learning.exam.attempt.errored.v1 # .. event_name: EXAM_ATTEMPT_ERRORED # .. event_description: Emitted when a learner's exam attempt errors out in edx-exams. -# .. event_data: SpecialExamAttemptData +# .. event_data: ExamAttemptData EXAM_ATTEMPT_ERRORED = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.errored.v1", data={ - "exam_attempt": SpecialExamAttemptData, + "exam_attempt": ExamAttemptData, } ) # .. event_type: org.openedx.learning.exam.attempt.reset.v1 # .. event_name: EXAM_ATTEMPT_RESET # .. event_description: Emitted when an exam attempt is reset in edx-exams. -# .. event_data: SpecialExamAttemptData +# .. event_data: ExamAttemptData EXAM_ATTEMPT_RESET = OpenEdxPublicSignal( event_type="org.openedx.learning.exam.attempt.reset.v1", data={ - "exam_attempt": SpecialExamAttemptData, + "exam_attempt": ExamAttemptData, } ) From d3c6581e5bc55cb785c575a89c6a3308d0d3d3e8 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Fri, 29 Sep 2023 14:20:21 -0400 Subject: [PATCH 25/30] docs: Added ADR Draft --- ...cial-exam-submission-and-review-events.rst | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 docs/decisions/0013-special-exam-submission-and-review-events.rst diff --git a/docs/decisions/0013-special-exam-submission-and-review-events.rst b/docs/decisions/0013-special-exam-submission-and-review-events.rst new file mode 100644 index 00000000..844d7e1a --- /dev/null +++ b/docs/decisions/0013-special-exam-submission-and-review-events.rst @@ -0,0 +1,37 @@ +12. Event definitions for special exam post-submission and review +################################################################# + +Status +****** + +**Draft** 2023-09-29 + +Context +******* + +* A new backend for exams called `edx-exams` is being developed (See the `exams IDA ADR `_ for more info). +* We are currently working to implement the downstream effects triggered whenever an exam attempt is submitted or reviewed. (For example, when an exam attempt is submitted, we will want to make sure `edx-platform` knows to mark the exam subsection as completed.) + + +Decision +******** + +* Since `edx-exams` is independent, we will want to prevent circular dependencies between `edx-platform` and `edx-exams`. +* We have defined the events that we plan to define in `this ADR `_ in `edx-exams` to use the event bus, as the new exams backend is independent in this ADR +* We plan for these events to be produced in `edx-exams`, and consumed in various `edx-platform` services (e.g. certificates, credit, instructor, grades). + +* Note that events that use the newly defined data type: + A. Pretain to "Special Exams", e.g. Timed or Proctored exams, and not non-timed course subsections that are labelled as an exam. + + B. Are only ever emitted from the newer exams backend, `edx-exams`, and never from the legacy exams backend, edx-proctoring. + +* For the event data and signal names, we are using the prefix "Exam" as opposed to the prefix `Special_Exam` because "special exams" will likely be the only type of exam that will be of concern to developers in the context of events/the event bus. + + +Consequences +************ + +* `Edx-exams` will emit events via the event bus to send information without needing a response. +* Since, `edx-exams` already recieves and responds to REST requests, we will avoid creating circular dependencies because `edx-exams` will not need to send REST requests itself. +* These events are dynamic, in that they can also be consumed in other places as needed. + From c1a196d1ce62a12b9fae8bb827ee09f51287932c Mon Sep 17 00:00:00 2001 From: ilee2u Date: Fri, 29 Sep 2023 14:24:55 -0400 Subject: [PATCH 26/30] chore: quality --- docs/decisions/index.rst | 1 + openedx_events/learning/signals.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/decisions/index.rst b/docs/decisions/index.rst index 81479709..a73a8b09 100644 --- a/docs/decisions/index.rst +++ b/docs/decisions/index.rst @@ -17,3 +17,4 @@ Architectural Decision Records (ADRs) 0010-multiple-event-types-per-topic 0011-depending-on-multiple-event-bus-implementations 0012-producing-to-event-bus-via-settings + 0013-special-exam-submission-and-review-events diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index 33e18084..ece24cf9 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -13,9 +13,9 @@ CohortData, CourseDiscussionConfigurationData, CourseEnrollmentData, + ExamAttemptData, PersistentCourseGradeData, ProgramCertificateData, - ExamAttemptData, UserData, UserNotificationData, XBlockSkillVerificationData, From d7ce2e528f9b1025778e609f7fa1254342950f45 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Fri, 29 Sep 2023 14:57:08 -0400 Subject: [PATCH 27/30] docs: removed non-event related decision info --- .../decisions/0013-special-exam-submission-and-review-events.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/decisions/0013-special-exam-submission-and-review-events.rst b/docs/decisions/0013-special-exam-submission-and-review-events.rst index 844d7e1a..458377f6 100644 --- a/docs/decisions/0013-special-exam-submission-and-review-events.rst +++ b/docs/decisions/0013-special-exam-submission-and-review-events.rst @@ -16,7 +16,6 @@ Context Decision ******** -* Since `edx-exams` is independent, we will want to prevent circular dependencies between `edx-platform` and `edx-exams`. * We have defined the events that we plan to define in `this ADR `_ in `edx-exams` to use the event bus, as the new exams backend is independent in this ADR * We plan for these events to be produced in `edx-exams`, and consumed in various `edx-platform` services (e.g. certificates, credit, instructor, grades). From 9e4744c41578fc42672edf4fe6e46b5ad986296c Mon Sep 17 00:00:00 2001 From: ilee2u Date: Mon, 2 Oct 2023 09:52:00 -0400 Subject: [PATCH 28/30] fix: improved ADR --- ...cial-exam-submission-and-review-events.rst | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/docs/decisions/0013-special-exam-submission-and-review-events.rst b/docs/decisions/0013-special-exam-submission-and-review-events.rst index 458377f6..d685f838 100644 --- a/docs/decisions/0013-special-exam-submission-and-review-events.rst +++ b/docs/decisions/0013-special-exam-submission-and-review-events.rst @@ -4,27 +4,42 @@ Status ****** -**Draft** 2023-09-29 +**Draft** 2023-10-02 Context ******* +About Special Exams: +==================== +* Course subsections that have an `exam_type` have additional logic that governs completion, grading, credit requirements, and more based on the `exam_type` value (e.g. timed, proctored, etc). +* These subsections are also known as **Special Exams**. + * NOTE: The events described in this document will only be produced/consumed in the context of **Special Exams**. +* Course subsections that do not have an `exam_type` configured may still have a grading policy named 'Exam'. This type of content does not have the exam user experience and is not governed by any exam specific logic. + +The New Exams IDA: +================== * A new backend for exams called `edx-exams` is being developed (See the `exams IDA ADR `_ for more info). -* We are currently working to implement the downstream effects triggered whenever an exam attempt is submitted or reviewed. (For example, when an exam attempt is submitted, we will want to make sure `edx-platform` knows to mark the exam subsection as completed.) +* We are currently working to use the event bus to trigger the downstream effects whenever an exam attempt is submitted or reviewed. + * For example, when an exam attempt is submitted, we will want to make sure `edx-platform` knows to mark the exam subsection as completed. Decision ******** -* We have defined the events that we plan to define in `this ADR `_ in `edx-exams` to use the event bus, as the new exams backend is independent in this ADR -* We plan for these events to be produced in `edx-exams`, and consumed in various `edx-platform` services (e.g. certificates, credit, instructor, grades). +Where these events will be produced/consumed: +============================================= -* Note that events that use the newly defined data type: - A. Pretain to "Special Exams", e.g. Timed or Proctored exams, and not non-timed course subsections that are labelled as an exam. +* `edx-exams` will produce these events. + * NOTE: There is no plan to have the legacy exams backend, `edx-proctoring`, produce these events. +* `edx-platform` will consumed these events in order to handle all behavior as it pertains to the state of an exam subsection. - B. Are only ever emitted from the newer exams backend, `edx-exams`, and never from the legacy exams backend, edx-proctoring. +Event Definitions: +================== +* We will define the events that as planned in `the ADR for events in edx-exams `_. -* For the event data and signal names, we are using the prefix "Exam" as opposed to the prefix `Special_Exam` because "special exams" will likely be the only type of exam that will be of concern to developers in the context of events/the event bus. +Note on the Event Data/Signal Names: +==================================== +We are using the prefix "Exam" as opposed to the prefix "Special_Exam" for these events because **Special Exams** will likely be the only type of exam that will be of concern to developers in the context of events for the forseeable future. Consequences @@ -32,5 +47,5 @@ Consequences * `Edx-exams` will emit events via the event bus to send information without needing a response. * Since, `edx-exams` already recieves and responds to REST requests, we will avoid creating circular dependencies because `edx-exams` will not need to send REST requests itself. -* These events are dynamic, in that they can also be consumed in other places as needed. +* These events are dynamic, in that they can also be consumed by other services/applications as needed in the future. From 63049466880a72f74ed84ebe959992af9c647bc7 Mon Sep 17 00:00:00 2001 From: ilee2u Date: Mon, 2 Oct 2023 10:31:49 -0400 Subject: [PATCH 29/30] chore: nit --- .../0013-special-exam-submission-and-review-events.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/decisions/0013-special-exam-submission-and-review-events.rst b/docs/decisions/0013-special-exam-submission-and-review-events.rst index d685f838..aa6f9ae0 100644 --- a/docs/decisions/0013-special-exam-submission-and-review-events.rst +++ b/docs/decisions/0013-special-exam-submission-and-review-events.rst @@ -31,7 +31,7 @@ Where these events will be produced/consumed: * `edx-exams` will produce these events. * NOTE: There is no plan to have the legacy exams backend, `edx-proctoring`, produce these events. -* `edx-platform` will consumed these events in order to handle all behavior as it pertains to the state of an exam subsection. +* `edx-platform` will consume these events in order to handle all behavior as it pertains to the state of an exam subsection. Event Definitions: ================== @@ -45,7 +45,7 @@ We are using the prefix "Exam" as opposed to the prefix "Special_Exam" for these Consequences ************ -* `Edx-exams` will emit events via the event bus to send information without needing a response. +* `edx-exams` will emit events via the event bus to send information without needing a response. * Since, `edx-exams` already recieves and responds to REST requests, we will avoid creating circular dependencies because `edx-exams` will not need to send REST requests itself. * These events are dynamic, in that they can also be consumed by other services/applications as needed in the future. From 80629ced9c624757945a8cd0aede620be7c5bbab Mon Sep 17 00:00:00 2001 From: ilee2u Date: Mon, 2 Oct 2023 10:59:26 -0400 Subject: [PATCH 30/30] chore: Add ADR link to exam event data --- openedx_events/learning/data.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index b004cc60..b4189f08 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -313,6 +313,9 @@ class ExamAttemptData: We are using this as a shortened form of the prefix `SPECIAL_EXAM` to avoid confusion, as these are likely the only type of exams that will be of concern in the context of events/the event bus. + For more information, please see the ADR relating to this event data: + https://github.com/openedx/openedx-events/blob/main/docs/decisions/0013-special-exam-submission-and-review-events.rst + Arguments: student_user (UserData): user object for the student to whom the exam attempt belongs course_key (CourseKey): identifier of the course to which the exam attempt belongs