From dbfe2e12299eb0126a8431d1231d3d25104df6bf Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Wed, 22 Jan 2025 10:36:06 +0100 Subject: [PATCH] docs: [FC-0074] include tooling and data attributes in references (#450) --- docs/concepts/openedx-events.rst | 2 +- docs/conf.py | 8 +- docs/how-tos/create-a-new-event.rst | 2 +- docs/reference/events-data.rst | 30 +++ docs/reference/events-tooling.rst | 7 + docs/reference/index.rst | 2 + openedx_events/analytics/data.py | 10 +- openedx_events/analytics/signals.py | 2 +- openedx_events/content_authoring/data.py | 107 +++++---- openedx_events/content_authoring/signals.py | 32 +-- openedx_events/data.py | 23 +- openedx_events/enterprise/data.py | 45 ++-- openedx_events/enterprise/signals.py | 4 + openedx_events/event_bus/avro/deserializer.py | 13 +- openedx_events/event_bus/avro/schema.py | 20 +- openedx_events/event_bus/avro/serializer.py | 21 +- openedx_events/exceptions.py | 3 + openedx_events/learning/data.py | 212 ++++++++++-------- openedx_events/learning/signals.py | 72 +++--- openedx_events/tooling.py | 72 +++--- openedx_events/utils.py | 14 +- 21 files changed, 394 insertions(+), 307 deletions(-) create mode 100644 docs/reference/events-data.rst create mode 100644 docs/reference/events-tooling.rst diff --git a/docs/concepts/openedx-events.rst b/docs/concepts/openedx-events.rst index 2d2a5f0f..b4a9bdb4 100644 --- a/docs/concepts/openedx-events.rst +++ b/docs/concepts/openedx-events.rst @@ -20,7 +20,7 @@ Events are primarily used as a communication method between internal services by How do Open edX Events work? ---------------------------- -Open edX Events are implemented by a class called `OpenEdxPublicSignal`_, which inherits from `Django's Signals class` and adds behaviors specific to the Open edX ecosystem. Thanks to this design, ``OpenEdxPublicSignal`` leverages the functionality of Django signals, allowing developers to apply their existing knowledge of the Django framework. +Open edX Events are implemented by a class called `OpenEdxPublicSignal`_, which inherits from `Django's Signals class` and adds behaviors specific to the Open edX ecosystem. Thanks to this design, ``OpenEdxPublicSignal`` leverages the functionality of Django signals, allowing developers to apply their existing knowledge of the Django framework. You can review the :doc:`Open edX Events Tooling <../reference/events-tooling>` documentation for more information on the tooling available for working with Open edX events. .. _events-architecture: diff --git a/docs/conf.py b/docs/conf.py index 77ad5adc..3e20683f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,9 +12,8 @@ # import os import re -# import sys -# sys.path.insert(0, os.path.abspath('.')) - +import sys +sys.path.insert(0, os.path.abspath('..')) # -- Project information ----------------------------------------------------- @@ -39,6 +38,9 @@ 'code_annotations.contrib.sphinx.extensions.openedx_events', 'sphinx.ext.intersphinx', 'code_annotations.contrib.sphinx.extensions.settings', + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.napoleon', ] # Add any paths that contain templates here, relative to this directory. diff --git a/docs/how-tos/create-a-new-event.rst b/docs/how-tos/create-a-new-event.rst index 63a33951..43bf3a4e 100644 --- a/docs/how-tos/create-a-new-event.rst +++ b/docs/how-tos/create-a-new-event.rst @@ -159,7 +159,7 @@ In our example, the event definition and payload for the enrollment event could - The payload should be an `attrs`_ class to ensure that the data is immutable by using the ``frozen=True`` argument and to ensure that the data is self-descriptive. - Use the ``attr.ib`` decorator to define the fields in the payload with the data type that the field should contain. Try to use the appropriate data type for each field to ensure that the data is consistent and maintainable, you can inspect the triggering logic to review the data that is available at the time the event is triggered. - Try using nested data classes to group related data together. This will help maintain consistency and make the event more readable. For instance, in the above example, we have grouped the data into User, Course, and Enrollment data. -- Try reusing existing data classes if possible to avoid duplicating data classes. This will help maintain consistency and reduce the chances of introducing errors. +- Try reusing existing data classes if possible to avoid duplicating data classes. This will help maintain consistency and reduce the chances of introducing errors. You can review the existing data classes in :doc:`../reference/events-data` to see if there is a data class that fits your use case. - Each field in the payload should be documented with a description of what the field represents and the data type it should contain. This will help consumers understand the payload and react to the event. You should be able to justify why each field is included in the payload and how it relates to the event. - Use defaults for optional fields in the payload to ensure its consistency in all cases. diff --git a/docs/reference/events-data.rst b/docs/reference/events-data.rst new file mode 100644 index 00000000..da8e5088 --- /dev/null +++ b/docs/reference/events-data.rst @@ -0,0 +1,30 @@ +Open edX Events Data Attributes +=============================== + +Here are the data classes and attributes available for use when creating new Open edX Events. Review the classes and attributes to understand the data available for use in your event before creating a new data classes. + +.. note:: If you are creating a new data class in a subdomain that is not listed here, please add the new data class to the appropriate new subdomain section. + +Learning Subdomain +------------------ + +.. automodule:: openedx_events.learning.data + :members: + +Content Authoring Subdomain +--------------------------- + +.. automodule:: openedx_events.content_authoring.data + :members: + +Analytics Subdomain +------------------- + +.. automodule:: openedx_events.analytics.data + :members: + +Enterprise Subdomain +-------------------- + +.. automodule:: openedx_events.enterprise.data + :members: diff --git a/docs/reference/events-tooling.rst b/docs/reference/events-tooling.rst new file mode 100644 index 00000000..67da4396 --- /dev/null +++ b/docs/reference/events-tooling.rst @@ -0,0 +1,7 @@ +Open edX Events Tooling +======================= + +Here we document the tooling available for working with Open edX events as a developer. + +.. autoclass:: openedx_events.tooling.OpenEdxPublicSignal + :members: diff --git a/docs/reference/index.rst b/docs/reference/index.rst index ac8d69b4..eeaa88ce 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -5,6 +5,8 @@ References :maxdepth: 1 :caption: Contents: + events-tooling + events-data events in-line-code-annotations-for-an-event glossary diff --git a/openedx_events/analytics/data.py b/openedx_events/analytics/data.py index 801ebdd5..51d00a60 100644 --- a/openedx_events/analytics/data.py +++ b/openedx_events/analytics/data.py @@ -13,15 +13,15 @@ @attr.s(frozen=True) class TrackingLogData: """ - Data describing tracking events. + Data related to tracking events. - Arguments: + Attributes: name (str): event name timestamp (datetime): timestamp of the event - data (str): json string representation of a dictionary with extra data (optional), - e.g. {"course_id": "course-v1:edX+DemoX+Demo_Course"} + data (str): json string representation of a dictionary with extra data (optional), e.g., + >>> {"course_id": "course-v1:edX+DemoX+Demo_Course"} context (dict): json string representation of a dictionary of context data - defined in https://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/ + defined in https://edx.readthedocs.io/projects/devdata/en/latest/internal_data_formats/tracking_logs/ """ name = attr.ib(type=str) diff --git a/openedx_events/analytics/signals.py b/openedx_events/analytics/signals.py index 6039aa86..fe0e623f 100644 --- a/openedx_events/analytics/signals.py +++ b/openedx_events/analytics/signals.py @@ -14,7 +14,7 @@ # .. event_type: org.openedx.analytics.tracking.event.emitted.v1 # .. event_name: TRACKING_EVENT_EMITTED # .. event_key_field: tracking_log.name -# .. event_description: emitted when a tracking log is created. +# .. event_description: Emitted when a tracking log event is emitted. # .. event_data: TrackingLogData # .. event_trigger_repository: openedx/event-tracking TRACKING_EVENT_EMITTED = OpenEdxPublicSignal( diff --git a/openedx_events/content_authoring/data.py b/openedx_events/content_authoring/data.py index e5d376fb..8e0be317 100644 --- a/openedx_events/content_authoring/data.py +++ b/openedx_events/content_authoring/data.py @@ -18,9 +18,9 @@ @attr.s(frozen=True) class CourseData: """ - Attributes defined for Open edX Course object. + Data related to a course object. - Arguments: + Attributes: course_key (CourseKey): identifier of the Course object. """ @@ -30,14 +30,14 @@ class CourseData: @attr.s(frozen=True) class CourseScheduleData: """ - Data describing course scheduling. + Data related to a course schedule. - Arguments: - start (datetime): course start date - pacing (str): 'instructor' or 'self' - end (datetime): course end date (optional) - enrollment_start (datetime): start of course enrollment (optional) - enrollment_end (datetime): end of course enrollment (optional) + Attributes: + start (datetime): course start date. + pacing (str): 'instructor' or 'self'. + end (datetime): course end date (optional). + enrollment_start (datetime): start of course enrollment (optional). + enrollment_end (datetime): end of course enrollment (optional). """ start = attr.ib(type=datetime) @@ -50,14 +50,14 @@ class CourseScheduleData: @attr.s(frozen=True) class CourseCatalogData: """ - Data needed for a course catalog entry. + Data related to a course catalog entry. - Arguments: + Attributes: course_key (CourseKey): identifier of the Course object. - name (str): course name - schedule_data (CourseScheduleData): scheduling information for the course - hidden (bool): whether the course is hidden from search (optional) - invitation_only (bool): whether the course requires an invitation to enroll + name (str): course name. + schedule_data (CourseScheduleData): scheduling information for the course. + hidden (bool): whether the course is hidden from search (optional). + invitation_only (bool): whether the course requires an invitation to enroll. """ # basic identifiers @@ -73,13 +73,13 @@ class CourseCatalogData: @attr.s(frozen=True) class XBlockData: """ - Data about changed XBlock. + Data related to an XBlock object. - Arguments: + Attributes: usage_key (UsageKey): identifier of the XBlock object. block_type (str): type of block. version (UsageKey): identifier of the XBlock object with branch and version data (optional). This - could be used to get the exact version of the XBlock object. + could be used to get the exact version of the XBlock object. """ usage_key = attr.ib(type=UsageKey) @@ -90,11 +90,11 @@ class XBlockData: @attr.s(frozen=True) class DuplicatedXBlockData(XBlockData): """ - Data about duplicated XBlock. + Data related to an XBlock object that has been duplicated. This class extends XBlockData to include source_usage_key. - Arguments: + Attributes: source_usage_key (UsageKey): identifier of the source XBlock object. """ @@ -104,13 +104,13 @@ class DuplicatedXBlockData(XBlockData): @attr.s(frozen=True) class CertificateSignatoryData: """ - Attributes defined for Open edX CertificateSignatory data object. + Data related to a certificate signatory. Subset of CertificateSignatory object from the LMS. - Arguments: - image (BinaryIO): certificate signature image. + Attributes: + image (BinaryIO): certificate signature image. Take care that the image field is BinaryIO. name (str): name of signatory. organization (str): organization that signatory belongs to. - title (int): signatory title. + title (str): signatory title. """ # Note: Please take care that the image field is BinaryIO, which means @@ -128,22 +128,22 @@ class CertificateSignatoryData: @attr.s(frozen=True) class CertificateConfigData: """ - Attributes defined for Open edX CertificateConfig data object. + Data related to a certificate configuration. Subset of CertificateConfig object from the LMS. - Arguments: + Attributes: certificate_type (str): certificate type. Possible types are certificate relevant course modes: - - credit, - - verified, - - professional, - - no-id-professional, - - executive-education, - - paid-executive-education, - - paid-bootcamp, - - masters. + - credit, + - verified, + - professional, + - no-id-professional, + - executive-education, + - paid-executive-education, + - paid-bootcamp, + - masters. course_key (CourseKey): identifier of the Course object. title (str): certificate title. signatories (List[CertificateSignatoryData]): contains a collection of signatures - that belong to the certificate configuration. + that belong to the certificate configuration. is_active (bool): indicates whether the certifivate configuration is active. """ @@ -157,11 +157,11 @@ class CertificateConfigData: @attr.s(frozen=True) class ContentLibraryData: """ - Data about changed ContentLibrary. + Data related to a content library that has changed. - Arguments: + Attributes: library_key (LibraryLocatorV2): a key that represents a Blockstore-based content library. - update_blocks (bool): flag that indicates whether the content library blocks indexes should be updated + update_blocks (bool): flag that indicates whether the content library blocks indexes should be updated. """ library_key = attr.ib(type=LibraryLocatorV2) @@ -171,9 +171,9 @@ class ContentLibraryData: @attr.s(frozen=True) class LibraryBlockData: """ - Data about changed LibraryBlock. + Data related to a library block that has changed. - Arguments: + Attributes: library_key (LibraryLocatorV2): a key that represents a Blockstore-based content library. usage_key (LibraryUsageLocatorV2): a key that represents a XBlock in a Blockstore-based content library. """ @@ -185,12 +185,12 @@ class LibraryBlockData: @attr.s(frozen=True) class ContentObjectData: """ - Data about a content object. + Data related to a content object. - Arguments: + Attributes: object_id (str): identifier of the Content object. This represents the id of the course or library block - as a string. For example: - block-v1:SampleTaxonomyOrg2+STC1+2023_1+type@vertical+block@f8de78f0897049ce997777a3a31b6ea0 + as a string. For example: + >>> block-v1:SampleTaxonomyOrg2+STC1+2023_1+type@vertical+block@f8de78f0897049ce997777a3a31b6ea0 """ object_id = attr.ib(type=str) @@ -199,15 +199,14 @@ class ContentObjectData: @attr.s(frozen=True) class ContentObjectChangedData(ContentObjectData): """ - Data about a changed content object. + Data related to a content object that has changed. - Arguments: + Attributes: object_id (str): identifier of the Content object. This represents the id of the course or library block - as a string. For example: - block-v1:SampleTaxonomyOrg2+STC1+2023_1+type@vertical+block@f8de78f0897049ce997777a3a31b6ea0 - - changes: list of changes made to this ContentObject, e.g. "tags", "collections" - If list is empty, assume everything has changed. + as a string. For example: + >>> block-v1:SampleTaxonomyOrg2+STC1+2023_1+type@vertical+block@f8de78f0897049ce997777a3a31b6ea0 + changes: list of changes made to this ContentObject, e.g. "tags", "collections". If list is empty, + assume everything has changed. """ changes = attr.ib(type=List[str], factory=list) @@ -216,13 +215,13 @@ class ContentObjectChangedData(ContentObjectData): @attr.s(frozen=True) class LibraryCollectionData: """ - Data about changed content library Collection. + Data related to a library collection that has changed. - Arguments: + Attributes: library_key (LibraryLocatorV2): a key that represents a Blockstore-based content library. collection_key (str): identifies the collection within the library's learning package background (bool): indicate whether the sender doesn't want to wait for handler to finish execution, - i.e., the handler can run the task in background. By default it is False. + i.e., the handler can run the task in background. By default it is False. """ library_key = attr.ib(type=LibraryLocatorV2) diff --git a/openedx_events/content_authoring/signals.py b/openedx_events/content_authoring/signals.py index 8b1aec35..1183f581 100644 --- a/openedx_events/content_authoring/signals.py +++ b/openedx_events/content_authoring/signals.py @@ -110,8 +110,9 @@ # .. event_type: org.openedx.content_authoring.course.certificate_config.changed.v1 # .. event_name: COURSE_CERTIFICATE_CONFIG_CHANGED # .. event_description: Fired when a course certificate configuration changes in Studio. -# .. event_warning: This event is currently incompatible with the event bus, list/dict cannot be serialized yet # .. event_data: CertificateConfigData +# .. event_warning: This event is not being currently used in any of the Open edX services. Review +# https://github.com/openedx/openedx-events/issues/445 for more information about the future of this event. COURSE_CERTIFICATE_CONFIG_CHANGED = OpenEdxPublicSignal( event_type="org.openedx.content_authoring.course.certificate_config.changed.v1", data={ @@ -122,8 +123,9 @@ # .. event_type: org.openedx.content_authoring.course.certificate_config.deleted.v1 # .. event_name: COURSE_CERTIFICATE_CONFIG_DELETED # .. event_description: Fired when a course certificate configuration deletes in Studio. -# .. event_warning: This event is currently incompatible with the event bus, list/dict cannot be serialized yet # .. event_data: CertificateConfigData +# .. event_warning: This event is not being currently used in any of the Open edX services. Review +# https://github.com/openedx/openedx-events/issues/445 for more information about the future of this event. COURSE_CERTIFICATE_CONFIG_DELETED = OpenEdxPublicSignal( event_type="org.openedx.content_authoring.course.certificate_config.deleted.v1", data={ @@ -133,7 +135,7 @@ # .. event_type: org.openedx.content_authoring.course.created.v1 # .. event_name: COURSE_CREATED -# .. event_description: emitted when a course is created +# .. event_description: Emitted when a course is created. # .. event_data: CourseData # .. event_trigger_repository: openedx/edx-platform COURSE_CREATED = OpenEdxPublicSignal( @@ -145,7 +147,7 @@ # .. event_type: org.openedx.content_authoring.content_library.created.v1 # .. event_name: CONTENT_LIBRARY_CREATED -# .. event_description: emitted when a content library is created +# .. event_description: Emitted when a content library is created. # .. event_data: ContentLibraryData # .. event_trigger_repository: openedx/edx-platform CONTENT_LIBRARY_CREATED = OpenEdxPublicSignal( @@ -157,7 +159,7 @@ # .. event_type: org.openedx.content_authoring.content_library.updated.v1 # .. event_name: CONTENT_LIBRARY_UPDATED -# .. event_description: emitted when a content library is updated +# .. event_description: Emitted when a content library is updated. # .. event_data: ContentLibraryData # .. event_trigger_repository: openedx/edx-platform CONTENT_LIBRARY_UPDATED = OpenEdxPublicSignal( @@ -169,7 +171,7 @@ # .. event_type: org.openedx.content_authoring.content_library.deleted.v1 # .. event_name: CONTENT_LIBRARY_DELETED -# .. event_description: emitted when a content library is deleted +# .. event_description: Emitted when a content library is deleted. # .. event_data: ContentLibraryData # .. event_trigger_repository: openedx/edx-platform CONTENT_LIBRARY_DELETED = OpenEdxPublicSignal( @@ -181,7 +183,7 @@ # .. event_type: org.openedx.content_authoring.library_block.created.v1 # .. event_name: LIBRARY_BLOCK_CREATED -# .. event_description: emitted when a library block is created +# .. event_description: Emitted when a library block is created. # .. event_data: LibraryBlockData # .. event_trigger_repository: openedx/edx-platform LIBRARY_BLOCK_CREATED = OpenEdxPublicSignal( @@ -193,7 +195,7 @@ # .. event_type: org.openedx.content_authoring.library_block.updated.v1 # .. event_name: LIBRARY_BLOCK_UPDATED -# .. event_description: emitted when a library block is updated +# .. event_description: Emitted when a library block is updated. # .. event_data: LibraryBlockData # .. event_trigger_repository: openedx/edx-platform LIBRARY_BLOCK_UPDATED = OpenEdxPublicSignal( @@ -205,7 +207,7 @@ # .. event_type: org.openedx.content_authoring.library_block.deleted.v1 # .. event_name: LIBRARY_BLOCK_DELETED -# .. event_description: emitted when a library block is deleted +# .. event_description: Emitted when a library block is deleted. # .. event_data: LibraryBlockData # .. event_trigger_repository: openedx/edx-platform LIBRARY_BLOCK_DELETED = OpenEdxPublicSignal( @@ -217,7 +219,7 @@ # .. event_type: org.openedx.content_authoring.content.object.associations.changed.v1 # .. event_name: CONTENT_OBJECT_ASSOCIATIONS_CHANGED -# .. event_description: emitted when an object's associations are changed, e.g tags, collections +# .. event_description: Emitted when an object's associations are changed, e.g tags, collections. # .. event_data: ContentObjectData # .. event_trigger_repository: openedx/edx-platform CONTENT_OBJECT_ASSOCIATIONS_CHANGED = OpenEdxPublicSignal( @@ -229,9 +231,9 @@ # .. event_type: org.openedx.content_authoring.content.object.tags.changed.v1 # .. event_name: CONTENT_OBJECT_TAGS_CHANGED -# .. event_description: emitted when an object's tags are changed -# DEPRECATED: please use CONTENT_OBJECT_ASSOCIATIONS_CHANGED instead. +# .. event_description: Emitted when an object's tags are changed. # .. event_data: ContentObjectData +# .. event_warning: **DEPRECATED** please use CONTENT_OBJECT_ASSOCIATIONS_CHANGED instead. CONTENT_OBJECT_TAGS_CHANGED = OpenEdxPublicSignal( event_type="org.openedx.content_authoring.content.object.tags.changed.v1", data={ @@ -241,7 +243,7 @@ # .. event_type: org.openedx.content_authoring.content_library.collection.created.v1 # .. event_name: LIBRARY_COLLECTION_CREATED -# .. event_description: emitted when a content library collection is created +# .. event_description: Emitted when a content library collection is created. # .. event_data: LibraryCollectionData # .. event_trigger_repository: openedx/edx-platform LIBRARY_COLLECTION_CREATED = OpenEdxPublicSignal( @@ -253,7 +255,7 @@ # .. event_type: org.openedx.content_authoring.content_library.collection.updated.v1 # .. event_name: LIBRARY_COLLECTION_UPDATED -# .. event_description: emitted when when a content library collection is updated +# .. event_description: Emitted when when a content library collection is updated. # .. event_data: LibraryCollectionData # .. event_trigger_repository: openedx/edx-platform LIBRARY_COLLECTION_UPDATED = OpenEdxPublicSignal( @@ -265,7 +267,7 @@ # .. event_type: org.openedx.content_authoring.content_library.collection.deleted.v1 # .. event_name: LIBRARY_COLLECTION_DELETED -# .. event_description: emitted when an when a content library collection is deleted +# .. event_description: Emitted when an when a content library collection is deleted. # .. event_data: LibraryCollectionData # .. event_trigger_repository: openedx/edx-platform LIBRARY_COLLECTION_DELETED = OpenEdxPublicSignal( diff --git a/openedx_events/data.py b/openedx_events/data.py index 962f6565..6aecdce1 100644 --- a/openedx_events/data.py +++ b/openedx_events/data.py @@ -58,18 +58,17 @@ class EventsMetadata: The attributes defined in this class are a subset of the OEP-41: Asynchronous Server Event Message Format. - Arguments: - id (UUID): event identifier. - event_type (str): name of the event. - minorversion (int): (optional) version of the event type. Defaults to 0. - source (str): logical source of an event. - sourcehost (str): physical source of the event. - time (datetime): (optional) timestamp when the event was sent with - UTC timezone. Defaults to current time in UTC. See OEP-41 for - details. - sourcelib (tuple of ints): Open edX Events library version. A tuple was - selected so that version comparisons don't have to worry about - lexical ordering of strings (e.g. '0.9.0' vs. '0.10.0'). + Attributes: + - id (UUID): event identifier. + - event_type (str): name of the event. + - minorversion (int): (optional) version of the event type. Defaults to 0. + - source (str): logical source of an event. + - sourcehost (str): physical source of the event. + - time (datetime): (optional) timestamp when the event was sent with UTC timezone. + Defaults to current time in UTC. See OEP-41 fordetails. + - sourcelib (tuple of ints): Open edX Events library version. A tuple was + selected so that version comparisons don't have to worry about lexical ordering of + strings (e.g. '0.9.0' vs. '0.10.0'). """ event_type = attr.ib(type=str, validator=attr.validators.instance_of(str)) diff --git a/openedx_events/enterprise/data.py b/openedx_events/enterprise/data.py index a8fa3933..fa728991 100644 --- a/openedx_events/enterprise/data.py +++ b/openedx_events/enterprise/data.py @@ -14,9 +14,9 @@ @attr.s(frozen=True) class SubsidyRedemption: """ - Attributes for a Subsidy Redemption object. + Data related to a Subsidy Redemption object. - Arguments: + Attributes: subsidy_identifier (str): unique identifier to fetch the applied subsidy content_key (str): content id where subsidy is utilized lms_user_id (str): lms user id of subsidy beneficiary @@ -30,7 +30,15 @@ class SubsidyRedemption: @attr.s(frozen=True) class BaseLedgerTransaction: """ - Defines the common attributes of the transaction classes below. + Data related to a Ledger Transaction object. + + Attributes: + uuid (UUID): Primary identifier of the record. + created (datetime): When the record was created. + modified (datetime): When the record was last modified. + idempotency_key (str): Client-generated unique value to achieve idempotency of operations. + quantity (int): How many units of value this transaction represents (e.g. USD cents). + state (str): Current lifecyle state of the record, one of (created, pending, committed, failed). """ uuid = attr.ib(type=UUID) @@ -51,7 +59,7 @@ class LedgerTransactionReversal(BaseLedgerTransaction): enterprise enrollments. https://github.com/openedx/openedx-ledger/blob/master/openedx_ledger/models.py - Arguments: + Attributes: uuid (str): Primary identifier of the record. created (datetime): When the record was created. modified (datetime): When the record was last modified. @@ -70,7 +78,7 @@ class LedgerTransaction(BaseLedgerTransaction): used within the domain of edX Enterprise for recording the redemption of subsidized enrollments. https://github.com/openedx/openedx-ledger/blob/master/openedx_ledger/models.py - Arguments: + Attributes: uuid (UUID): Primary identifier of the Transaction. created (datetime): When the record was created. modified (datetime): When the record was last modified. @@ -83,7 +91,7 @@ class LedgerTransaction(BaseLedgerTransaction): content_key (CourseKey): The course (run) key associated with this transaction. parent_content_key (str): The parent (just course, not run) key for the course key. fulfillment_identifier (str): The identifier of the subsidized enrollment record for a learner, - generated durning enrollment. + generated durning enrollment. reversal (LedgerTransactionReversal): Any reversal associated with this transaction. """ @@ -99,11 +107,11 @@ class LedgerTransaction(BaseLedgerTransaction): @attr.s(frozen=True) class EnterpriseCustomerUser: """ - Attributes of an ``enterprise.EnterpriseCustomerUser`` record. + Data related to an Enterprise Customer User object. Django model definition: https://github.com/openedx/edx-enterprise/blob/cc873d6/enterprise/models.py#L1036 - Arguments: + Attributes: id (int): Primary identifier of the record. created (datetime): When the record was created. modified (datetime): When the record was last modified. @@ -114,7 +122,7 @@ class EnterpriseCustomerUser: is_relinkable (bool): When set to False, the user cannot be relinked to the enterprise. invite_key (UUID): Invite key used to link a learner to an enterprise. should_inactivate_other_customers (bool): When enabled along with `active`, all other linked enterprise - customers for this user will be marked as inactive upon save. + customers for this user will be marked as inactive upon save. """ id = attr.ib(type=int) @@ -132,11 +140,11 @@ class EnterpriseCustomerUser: @attr.s(frozen=True) class EnterpriseCourseEnrollment: """ - Attributes of an ``enterprise.EnterpriseCourseEnrollment`` record. + Data related to an Enterprise Course Enrollment object. Django model definition: https://github.com/openedx/edx-enterprise/blob/cc873d6/enterprise/models.py#L1983 - Arguments: + Attributes: id (int): Primary identifier of the record. created (datetime): When the record was created. modified (datetime): When the record was last modified. @@ -166,13 +174,14 @@ class BaseEnterpriseFulfillment: Django model definition: https://github.com/openedx/edx-enterprise/blob/cc873d6/enterprise/models.py#L2213 - Arguments: + Attributes: uuid (str): Primary identifier of the record. created (datetime): When the record was created. modified (datetime): When the record was last modified. fulfillment_type (str): Subsidy fulfillment type, typical values: "license", "learner_credit", "coupon_code". enterprise_course_entitlement_uuid (UUID): The course entitlement the associated subsidy is for. - enterprise_course_enrollment (EnterpriseCourseEnrollment): The course enrollment the associated subsidy is for. + enterprise_course_enrollment (EnterpriseCourseEnrollment): The course enrollment the associated subsidy is + for. is_revoked (bool): Whether the enterprise subsidy is revoked, e.g., when a user's license is revoked. """ @@ -192,8 +201,9 @@ class LearnerCreditEnterpriseCourseEnrollment(BaseEnterpriseFulfillment): Django model definition: https://github.com/openedx/edx-enterprise/blob/cc873d6/enterprise/models.py#L2325 - Arguments: - (All of the same from BaseEnterpriseFulfillment plus the following:) + All of the same attributes from BaseEnterpriseFulfillment plus the following: + + Attributes: transaction_id (UUID): Ledgered transaction UUID to associate with this learner credit fulfillment. """ @@ -207,8 +217,9 @@ class LicensedEnterpriseCourseEnrollment(BaseEnterpriseFulfillment): Django model definition: https://github.com/openedx/edx-enterprise/blob/cc873d6/enterprise/models.py#L2355 - Arguments: - (All of the same from BaseEnterpriseFulfillment plus the following:) + All of the same attributes from BaseEnterpriseFulfillment plus the following: + + Attributes: license_uuid (UUID): License UUID to associate with this enterprise license fulfillment. """ diff --git a/openedx_events/enterprise/signals.py b/openedx_events/enterprise/signals.py index e46e3160..01e227cc 100644 --- a/openedx_events/enterprise/signals.py +++ b/openedx_events/enterprise/signals.py @@ -15,6 +15,8 @@ # .. event_name: SUBSIDY_REDEEMED # .. event_description: emitted when an enterprise subsidy is utilized. # .. event_data: SubsidyRedemption +# .. event_warning: This event is not being currently used in any of the Open edX services. Review +# https://github.com/openedx/openedx-events/issues/445 for more information about the future of this event. SUBSIDY_REDEEMED = OpenEdxPublicSignal( event_type="org.openedx.enterprise.subsidy.redeemed.v1", data={ @@ -26,6 +28,8 @@ # .. event_name: SUBSIDY_REDEMPTION_REVERSED # .. event_description: emitted when an enterprise subsidy is reversed. # .. event_data: SubsidyRedemption +# .. event_warning: This event is not being currently used in any of the Open edX services. Review +# https://github.com/openedx/openedx-events/issues/445 for more information about the future of this event. SUBSIDY_REDEMPTION_REVERSED = OpenEdxPublicSignal( event_type="org.openedx.enterprise.subsidy.redemption-reversed.v1", data={ diff --git a/openedx_events/event_bus/avro/deserializer.py b/openedx_events/event_bus/avro/deserializer.py index 442a9780..9bf07cff 100644 --- a/openedx_events/event_bus/avro/deserializer.py +++ b/openedx_events/event_bus/avro/deserializer.py @@ -27,6 +27,7 @@ def _deserialized_avro_record_dict_to_object(data: dict, data_type, deserializer data: Dictionary representation of an Avro record data_type: Desired Python data type, eg `str`, `CourseKey`, `CourseEnrollmentData` deserializers: Map of Python data type to deserializer method + Returns: An instance of data_type """ @@ -72,12 +73,12 @@ def _avro_record_dict_to_event_data(signal, avro_record_dict, deserializers=None Convert an Avro record dictionary into event data that can be sent by the given signal. Arguments: - signal: An instance of OpenEdxPublicSignal - avro_record_dict: Dictionary representation of an Avro record - deserializers: Map of Python data type to deserializer method + - signal: An instance of OpenEdxPublicSignal + - avro_record_dict: Dictionary representation of an Avro record + - deserializers: Map of Python data type to deserializer method Returns: - An event data dictionary that can be sent by the given signal + - An event data dictionary that can be sent by the given signal """ return {data_key: _deserialized_avro_record_dict_to_object(avro_record_dict[data_key], data_type, deserializers) for data_key, data_type in signal.init_data.items()} @@ -115,7 +116,7 @@ def __init__(self, signal): Initialize deserializer, creating an Avro schema from signal. Arguments: - signal: An instance of OpenEdxPublicSignal + signal: An instance of OpenEdxPublicSignal. """ self.signal = signal self.deserializers = {ext.cls: ext.deserialize for ext in self.custom_type_serializers()} @@ -135,6 +136,6 @@ def custom_type_serializers(self): Override this method to add custom serializers for unhandled classes. Returns: - A list of subclasses of BaseCustomTypeAvroSerializer + - A list of subclasses of BaseCustomTypeAvroSerializer """ return [] diff --git a/openedx_events/event_bus/avro/schema.py b/openedx_events/event_bus/avro/schema.py index afb03086..5d23d0de 100644 --- a/openedx_events/event_bus/avro/schema.py +++ b/openedx_events/event_bus/avro/schema.py @@ -18,8 +18,11 @@ def schema_from_signal(signal, custom_type_to_avro_type=None): Create an Avro schema for events sent by an instance of OpenEdxPublicSignal. Arguments: - signal: An instance of OpenEdxPublicSignal - custom_type_to_avro_type: A map of Python class to Avro type + - signal: An instance of OpenEdxPublicSignal + - custom_type_to_avro_type: A map of Python class to Avro type + + Returns: + - An Avro schema definition for the event. """ field_types = custom_type_to_avro_type or {} all_custom_field_types = {**DEFAULT_FIELD_TYPES, **field_types} @@ -46,11 +49,14 @@ def _create_avro_field_definition(data_key, data_type, previously_seen_types, Create an Avro schema field definition from an OpenEdxPublicSignal data definition. Arguments: - data_key: Field name, eg `lms_user_id`, `course_id`, `enrollment_status` - data_type: Python data type, eg `str`, `CourseKey`, `CourseEnrollmentData` - previously_seen_types: list of previously-encountered data types - custom_type_to_avro_type: map of custom data types to a pre-determined avro field type - default_is_none: boolean indicating whether this field has 'None' as a default + - data_key: Field name, eg `lms_user_id`, `course_id`, `enrollment_status`. + - data_type: Python data type, eg `str`, `CourseKey`, `CourseEnrollmentData`. + - previously_seen_types: list of previously-encountered data types. + - custom_type_to_avro_type: map of custom data types to a pre-determined avro field type. + - default_is_none: boolean indicating whether this field has 'None' as a default. + + Returns: + - An Avro field definition. """ field = {"name": data_key} all_field_type_overrides = custom_type_to_avro_type or {} diff --git a/openedx_events/event_bus/avro/serializer.py b/openedx_events/event_bus/avro/serializer.py index bd57183c..593a8a4f 100644 --- a/openedx_events/event_bus/avro/serializer.py +++ b/openedx_events/event_bus/avro/serializer.py @@ -18,10 +18,10 @@ def _get_non_attrs_serializer(serializers=None): Create a method to pass as the value_serializer argument to attr.as_dict to serialize using custom serializers. Arguments: - serializers: A map of Python type to serialization method + - serializers: A map of Python type to serialization method. Returns: - A method for serializing non_attrs values + - A method for serializing non_attrs values. """ param_serializers = serializers or {} all_serializers = {**DEFAULT_SERIALIZERS, **param_serializers} @@ -59,11 +59,11 @@ def _event_data_to_avro_record_dict(event_data, serializers=None): Create an Avro record dictionary from an event data dict. Arguments: - event_data: A dictionary representing an event sent by an instance of OpenEdxPublicSignal - serializers: A map of Python type to serialization method + - event_data: A dictionary representing an event sent by an instance of OpenEdxPublicSignal. + - serializers: A map of Python type to serialization method. Returns: - An Avro record dictionary representation of the event data + - An Avro record dictionary representation of the event data. """ def value_to_dict(value): @@ -84,10 +84,11 @@ def serialize_event_data_to_bytes(event_data, signal): Serialize event data to bytes. Arguments: - event_data: Event data to be sent via an OpenEdxPublicSignal's send_event method - signal: An instance of OpenEdxPublicSignal + - event_data: Event data to be sent via an OpenEdxPublicSignal's send_event method. + - signal: An instance of OpenEdxPublicSignal. + Returns: - bytes: Byte representation of the event_data, to be sent over the wire + bytes: Byte representation of the event_data, to be sent over the wire. """ serializer = AvroSignalSerializer(signal) schema_dict = serializer.schema @@ -115,7 +116,7 @@ def __init__(self, signal): Initialize serializer, creating an Avro schema from signal. Arguments: - signal: An instance of OpenEdxPublicSignal + signal: An instance of OpenEdxPublicSignal. """ self.signal = signal self.serializers = {ext.cls: ext.serialize for ext in self.custom_type_serializers()} @@ -135,6 +136,6 @@ def custom_type_serializers(self): Override this method to add custom serializers for unhandled classes. Returns: - A list of subclasses of BaseCustomTypeAvroSerializer + - A list of subclasses of BaseCustomTypeAvroSerializer """ return [] diff --git a/openedx_events/exceptions.py b/openedx_events/exceptions.py index e75f32bb..339e540c 100644 --- a/openedx_events/exceptions.py +++ b/openedx_events/exceptions.py @@ -21,6 +21,9 @@ def __init__(self, message=""): def __str__(self): """ Show string representation of OpenEdxEventException using its message. + + Returns: + str: message describing why the exception was raised. """ return self.message diff --git a/openedx_events/learning/data.py b/openedx_events/learning/data.py index 962dda35..afb0aab4 100644 --- a/openedx_events/learning/data.py +++ b/openedx_events/learning/data.py @@ -15,9 +15,9 @@ @attr.s(frozen=True) class UserNonPersonalData: """ - Attributes defined for Open edX user object based on non-PII data. + Data related to a user object that does not contain personal information (PII). - Arguments: + Attributes: id (int): unique identifier for the Django User object. is_active (bool): indicates whether the user is active. """ @@ -29,12 +29,12 @@ class UserNonPersonalData: @attr.s(frozen=True) class UserPersonalData: """ - Attributes defined for Open edX user object based on PII data. + Data related to a user object that contains personal information (PII). - Arguments: - username (str): username associated with the Open edX user. - email (str): email associated with the Open edX user. - name (str): name associated with the Open edX user's profile. + Attributes: + username (str): username associated with the user. + email (str): email associated with the user. + name (str): name associated with the user's profile. """ username = attr.ib(type=str) @@ -45,12 +45,13 @@ class UserPersonalData: @attr.s(frozen=True) class UserData(UserNonPersonalData): """ - Attributes defined for Open edX user object. + Data related to a user object, including personal information and non-personal information. - This class extends UserNonPersonalData to include PII data completing the - user object. + This class extends UserNonPersonalData to include PII data completing the user object. - Arguments: + Attributes: + id (int): unique identifier for the Django User object. + is_active (bool): indicates whether the user is active. pii (UserPersonalData): user's Personal Identifiable Information. """ @@ -60,13 +61,16 @@ class UserData(UserNonPersonalData): @attr.s(frozen=True) class CourseData: """ - Attributes defined for Open edX Course Overview object. + Data related to a course object. - Arguments: - course_key (str): identifier of the Course object. + This data is based on the fields available in the CourseOverview data model + defined in the course_overviews app. + + Attributes: + course_key (str): identifier of the course. display_name (str): display name associated with the course. - start (datetime): start date for the course. - end (datetime): end date for the course. + start (datetime): start date for the course. Defaults to None. + end (datetime): end date for the course. Defaults to None. """ course_key = attr.ib(type=CourseKey) @@ -88,7 +92,7 @@ class CcxCourseData: start (str, optional): The start date of the CCX course. Defaults to None, indicating no specific start date. end (str, optional): The end date of the CCX course. Defaults to None, indicating no specific end date. max_students_allowed (int, optional): The maximum number of students that can enroll in the CCX course. - Defaults to None, indicating no limit. + Defaults to None, indicating no limit. """ ccx_course_key = attr.ib(type=CCXLocator) @@ -103,9 +107,12 @@ class CcxCourseData: @attr.s(frozen=True) class CourseEnrollmentData: """ - Attributes defined for Open edX Course Enrollment object. + Data related to a course enrollment object. + + This data is based on the fields available in the CourseEnrollment data model + defined in the student app. - Arguments: + Attributes: user (UserData): user associated with the Course Enrollment. course (CourseData): course where the user is enrolled in. mode (str): course mode associated with the course enrollment. @@ -125,9 +132,12 @@ class CourseEnrollmentData: @attr.s(frozen=True) class CertificateData: """ - Attributes defined for Open edX Certificate data object. + Data related to a certificate object. + + This data is based on the GeneratedCertificate data model defined in the + certificates app. - Arguments: + Attributes: user (UserData): user associated with the Certificate. course (CourseData): course where the user obtained the certificate. mode (str): course mode associated with the course enrollment. @@ -151,9 +161,12 @@ class CertificateData: @attr.s(frozen=True) class CohortData: """ - Attributes defined for Open edX Cohort Membership object. + Attributes defined for cohort membership object. + + This data is based on the fields available in the CohortMembership data model + defined in the cohorts app. - Arguments: + Attributes: user (UserData): user assigned to the group. course (CourseData): course associated with the course group. name (str): name of the cohort group. @@ -167,20 +180,20 @@ class CohortData: @attr.s(frozen=True) class DiscussionTopicContext: """ - Attributes defined for Open edX Discussion Topic Context object. + Data related to a discussion topic context. Context for linking the external id for a discussion topic to its associated usage key. - Arguments: + Attributes: title (str): title of the discussion. This field is cached to improve the performance, since otherwise we'd - need to look it up in the course structure each time. + need to look it up in the course structure each time. usage_key (str): unit location. group_id (Optional[int]): can be used for providers that don't internally support - cohorting but we can emulate that with different contexts for different groups. + cohorting but we can emulate that with different contexts for different groups. external_id (str): store the commentable id that is used by cs_comments_service. ordering (int): represent the position of the discussion topic. context (dict): additional structured information about the context in - which this topic is used, such as the section, subsection etc. + which this topic is used, such as the section, subsection etc. """ title = attr.ib(type=str) @@ -194,20 +207,19 @@ class DiscussionTopicContext: @attr.s(frozen=True) class CourseDiscussionConfigurationData: """ - Attributes defined for Open edX Course Discussion Configuration Data object. + Data related to a course discussion configuration object. Course configuration information for discussions. Contains all the metadata needed to configure discussions for a course. - Arguments: + Attributes: course_key (str): identifier of the course to which the discussion belongs. provider_type (str): provider type from discussion settings. enable_in_context (bool): indicates whether in-context discussion is enabled for the course enable_graded_units (bool): If enabled, discussion topics will be created for graded units as well. unit_level_visibility (bool): visibility for unit level. plugin_configuration (dict): The plugin configuration data for this context/provider. - contexts (List[DiscussionTopicContext]): contains all the contexts for which discussion - is to be enabled. + contexts (List[DiscussionTopicContext]): contains all the contexts for which discussion is to be enabled. """ course_key = attr.ib(type=CourseKey) @@ -222,9 +234,12 @@ class CourseDiscussionConfigurationData: @attr.s(frozen=True) class PersistentCourseGradeData: """ - Attributes defined for Open edX PersistentCourseGrade data object. + Data related to a persistent course grade object. + + This data is based on the fields available in the PersistentCourseGrade data model + defined in the grades app. - Arguments: + Attributes: user_id (int): identifier of the grade to which the grade belongs. course (CourseData): Identifier of the course to which the grade belongs. course_edited_timestamp (datetime): date the course was edited. @@ -248,11 +263,11 @@ class PersistentCourseGradeData: @attr.s(frozen=True) class XBlockSkillVerificationData: """ - Data needed to update verification count of tags/skills for an XBlock. + Data needed to update verification count of tags/skills for an XBlock. User feedback on whether tags/skills related to an XBlock are valid. - Arguments: + Attributes: usage_key (UsageKey): identifier of the XBlock object. verified_skills (List[int]): list of verified skill ids. ignored_skills (List[int]): list of ignored skill ids. @@ -266,9 +281,9 @@ class XBlockSkillVerificationData: @attr.s(frozen=True) class UserNotificationData: """ - Attributes defined for Open edX User Notification data object. + Data related to a user notification object. - Arguments: + Attributes: user_ids (List(int)): identifier of the users to which the notification belongs. notification_type (str): type of the notification. content_url (str): url of the content. @@ -288,12 +303,12 @@ class UserNotificationData: @attr.s(frozen=True) class ProgramData: """ - Attributes defined for the Open edX Program data object. + Data related to a program object. - Arguments: - uuid (str): The UUID of the program (from Course-Discovery) - title (str): The title of the program - program_type (str): The type slug of the program (e.g. professional, microbachelors, micromasters, etc.) + Attributes: + uuid (str): The UUID of the program (from Course-Discovery). + title (str): The title of the program. + program_type (str): The type slug of the program (e.g. professional, microbachelors, micromasters, etc.). """ uuid = attr.ib(type=str) @@ -304,16 +319,16 @@ class ProgramData: @attr.s(frozen=True) class ProgramCertificateData: """ - Attributes defined for the Open edX Program Certificate data object. + Data related to a Program Certificate object. - Arguments: - user (UserData): User associated with the Program Certificate - program (ProgramData): Program data associated with the Program Certificate - uuid (str): UUID of the UserCredential record in Credentials + Attributes: + user (UserData): User associated with the Program Certificate. + program (ProgramData): Program data associated with the Program Certificate. + uuid (str): UUID of the UserCredential record in Credentials. certificate_available_date (datetime): Optional. A DateTime describing when a learner is allowed to view the - credential - status (str): The status of the credential (e.g. `awarded` or `revoked`) - url (str): A URL to the learner's credential + credential. + status (str): The status of the credential (e.g. `awarded` or `revoked`). + url (str): A URL to the learner's credential. """ user = attr.ib(type=UserData) @@ -327,7 +342,7 @@ class ProgramCertificateData: @attr.s(frozen=True) class ExamAttemptData: """ - Attributes defined for the Open edX Exam downstream effects. + Data 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 @@ -342,7 +357,7 @@ class ExamAttemptData: 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: + Attributes: 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 @@ -360,11 +375,11 @@ class ExamAttemptData: @attr.s(frozen=True) class CourseAccessRoleData: """ - Attributes defined for the Open edX Course Access Role data object. + Data related to a user's access role in a course. - Arguments: + Attributes: user (UserData): user associated with the CourseAccessRole. - course_key (CourseKey): identifer of the related course object. + course_key (CourseKey): identifier of the related course object. org (str): identifier of the organization. role (str): the role of the user in the course. """ @@ -378,12 +393,12 @@ class CourseAccessRoleData: @attr.s(frozen=True) class DiscussionThreadData: """ - Attributes defined for the Open edX to represent events in the Forum such as comments, responses, and threads. + Data related to a discussion thread object, used to represent Forum events such as comments, responses, and threads. For more details on the data attributes, please see the following documentation: https://docs.openedx.org/en/latest/developers/references/internal_data_formats/tracking_logs/student_event_types.html#edx-forum-thread-created - Arguments: + Attributes: anonymous (bool): indicates whether the user is anonymous. anonymous_to_peers (bool): indicates whether the user is anonymous to peers. body (str): body of the discussion thread. @@ -431,37 +446,37 @@ class DiscussionThreadData: @attr.s(frozen=True) class CourseNotificationData: """ - Attributes defined for Open edX Course Notification data object. + Data related to a course notification object. - Arguments: + Attributes: course_key (str): identifier of the Course object. app_name (str): name of the app requesting the course notification. notification_type (str): type of the notification. content_url (str): url of the content the notification will redirect to. content_context (dict): additional information related to the content of the notification. - Notification content templates are defined in edx-platform here: - https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/notifications/base_notification.py#L10 + Notification content templates are defined in edx-platform here: + https://github.com/openedx/edx-platform/blob/master/openedx/core/djangoapps/notifications/base_notification.py#L10 + audience_filters (dict): additional information related to the audience of the notification. + We can have different filters on course level, such as roles, enrollments, cohorts etc. - Example of content_context for a discussion notification (new_comment_on_response): + Example of content_context for a discussion notification: - { - ..., - "content_context": { - "post_title": "Post Title", - "replier_name": "test_user", - } + >>> { + ..., + "content_context": { + "post_title": "Post Title", + "replier_name": "test_user", + } - audience_filters (dict): additional information related to the audience of the notification. - We can have different filters on course level, such as roles, enrollments, cohorts etc. - Example of audience_filters for a discussion notification (new_discussion_post): + Example of audience_filters for a discussion notification (new_discussion_post): - { - ..., - "audience_filters": { - "enrollment": ["verified", "audit"], - "role": ["discussion admin", "discussion moderator"], - } + >>> { + ..., + "audience_filters": { + "enrollment": ["verified", "audit"], + "role": ["discussion admin", "discussion moderator"], + } """ course_key = attr.ib(type=CourseKey) @@ -475,9 +490,9 @@ class CourseNotificationData: @attr.s(frozen=True) class ORASubmissionAnswer: """ - Attributes defined to represent the answer submitted by the user in an ORA submission. + Data related to the answer submitted by the user in an ORA submission. - Arguments: + Attributes: parts (List[dict]): List with the response text in the ORA submission. The following attributes are used to represent the files submitted in the ORA submission: @@ -500,9 +515,9 @@ class ORASubmissionAnswer: @attr.s(frozen=True) class ORASubmissionData: """ - Attributes defined to represent event when a user submits an ORA assignment. + Data associated to the ORA assessment submitted by a user. - Arguments: + Attributes: uuid (str): The UUID of the ORA submission. anonymous_user_id (str): Optional. Anonymous user ID of the user who submitted the ORA submission. location (str): Optional. Location of the ORA submission. @@ -530,7 +545,7 @@ class CoursePassingStatusData: is_passing (bool): Indicates whether the user's grade is enough to pass the course. user (UserData): An instance of UserData containing information about the user whose grade was updated. course (CourseData): An instance of CourseData containing details about the course - in which the grade was updated. + in which the grade was updated. """ is_passing = attr.ib(type=bool) @@ -548,7 +563,8 @@ class CcxCoursePassingStatusData(CoursePassingStatusData): Attributes: course (CcxCourseData): An instance of CcxCourseData containing details about the CCX course - in which the grade threshold was crossed. + in which the grade threshold was crossed. + All other attributes are inherited from CoursePassingStatusData. """ @@ -558,14 +574,14 @@ class CcxCoursePassingStatusData(CoursePassingStatusData): @attr.s(frozen=True) class BadgeTemplateData: """ - Attributes defined for Open edX badge template data object. + Data related to a badge template object. - Arguments: - uuid (str): UUID of the badge template - origin (str): type of badge template - name (str): badge name - description (str): badge description - image_url (str): badge image url + Attributes: + uuid (str): UUID of the badge template. + origin (str): type of badge template. + name (str): badge name. + description (str): badge description. + image_url (str): badge image url. """ uuid = attr.ib(type=str) @@ -578,12 +594,12 @@ class BadgeTemplateData: @attr.s(frozen=True) class BadgeData: """ - Attributes defined for the Open edX badge data object. + Data related to a badge object. - Arguments: - uuid (str): the UUID of the badge - user (UserData): user associated with the badge - template (BadgeTemplateData): badge template data + Attributes: + uuid (str): the UUID of the badge. + user (UserData): user associated with the badge. + template (BadgeTemplateData): badge template data. """ uuid = attr.ib(type=str) @@ -594,9 +610,9 @@ class BadgeData: @attr.s(frozen=True) class VerificationAttemptData: """ - Attributes defined for the Open edX IDV attempt data object. + Data related to a IDV attempt object. - Arguments: + Attributes: attempt_id (int): the id of the verification attempt user (User): the user (usually a learner) performing the verification attempt. status (string): the status of the verification attempt. diff --git a/openedx_events/learning/signals.py b/openedx_events/learning/signals.py index 6f6a164f..62a08ba8 100644 --- a/openedx_events/learning/signals.py +++ b/openedx_events/learning/signals.py @@ -33,7 +33,7 @@ # .. event_type: org.openedx.learning.student.registration.completed.v1 # .. event_name: STUDENT_REGISTRATION_COMPLETED # .. event_key_field: user.pii.username -# .. event_description: emitted when the user registration process in the LMS is completed. +# .. event_description: Emitted when a user completes registration in Open edX. # .. event_data: UserData # .. event_trigger_repository: openedx/edx-platform STUDENT_REGISTRATION_COMPLETED = OpenEdxPublicSignal( @@ -47,7 +47,7 @@ # .. event_type: org.openedx.learning.auth.session.login.completed.v1 # .. event_name: SESSION_LOGIN_COMPLETED # .. event_key_field: user.pii.username -# .. event_description: emitted when the user's login process in the LMS is completed. +# .. event_description: Emitted when a user logs in to Open edX. # .. event_data: UserData # .. event_trigger_repository: openedx/edx-platform SESSION_LOGIN_COMPLETED = OpenEdxPublicSignal( @@ -61,7 +61,7 @@ # .. event_type: org.openedx.learning.course.enrollment.created.v1 # .. event_name: COURSE_ENROLLMENT_CREATED # .. event_key_field: enrollment.course.course_key -# .. event_description: emitted when the user's enrollment process is completed. +# .. event_description: Emitted when the user enrolls in a course. # .. event_data: CourseEnrollmentData # .. event_trigger_repository: openedx/edx-platform COURSE_ENROLLMENT_CREATED = OpenEdxPublicSignal( @@ -75,7 +75,7 @@ # .. event_type: org.openedx.learning.course.enrollment.changed.v1 # .. event_name: COURSE_ENROLLMENT_CHANGED # .. event_key_field: enrollment.course.course_key -# .. event_description: emitted when the user's enrollment update process is completed. +# .. event_description: Emitted when the enrollment for a user in a course changes. # .. event_data: CourseEnrollmentData # .. event_trigger_repository: openedx/edx-platform COURSE_ENROLLMENT_CHANGED = OpenEdxPublicSignal( @@ -89,7 +89,7 @@ # .. event_type: org.openedx.learning.course.unenrollment.completed.v1 # .. event_name: COURSE_UNENROLLMENT_COMPLETED # .. event_key_field: enrollment.course.course_key -# .. event_description: emitted when the user's unenrollment process is completed. +# .. event_description: Emitted when the user unenrolls from a course. # .. event_data: CourseEnrollmentData # .. event_trigger_repository: openedx/edx-platform COURSE_UNENROLLMENT_COMPLETED = OpenEdxPublicSignal( @@ -103,7 +103,7 @@ # .. event_type: org.openedx.learning.certificate.created.v1 # .. event_name: CERTIFICATE_CREATED # .. event_key_field: certificate.course.course_key -# .. event_description: emitted when the user's certificate creation process is completed. +# .. event_description: Emitted when a certificate is created for a user. # .. event_data: CertificateData # .. event_trigger_repository: openedx/edx-platform CERTIFICATE_CREATED = OpenEdxPublicSignal( @@ -116,7 +116,7 @@ # .. event_type: org.openedx.learning.program.certificate.awarded.v1 # .. event_name: PROGRAM_CERTIFICATE_AWARDED # .. event_key_field: program_certificate.program.uuid -# .. event_description: Emit when a program certificate is awarded to a learner +# .. event_description: Emitted when a program certificate is awarded to a learner. # .. event_data: ProgramCertificateData # .. event_trigger_repository: openedx/credentials PROGRAM_CERTIFICATE_AWARDED = OpenEdxPublicSignal( @@ -128,7 +128,7 @@ # .. event_type: org.openedx.learning.certificate.changed.v1 # .. event_name: CERTIFICATE_CHANGED -# .. event_description: emitted when the user's certificate update process is completed. +# .. event_description: Emitted when the user's certificate changes. # .. event_data: CertificateData # .. event_trigger_repository: openedx/edx-platform CERTIFICATE_CHANGED = OpenEdxPublicSignal( @@ -142,7 +142,7 @@ # .. event_type: org.openedx.learning.certificate.revoked.v1 # .. event_name: CERTIFICATE_REVOKED # .. event_key_field: certificate.course.course_key -# .. event_description: emitted when the user's certificate annulation process is completed. +# .. event_description: Emitted when a certificate is revoked from a user. # .. event_data: CertificateData # .. event_trigger_repository: openedx/edx-platform CERTIFICATE_REVOKED = OpenEdxPublicSignal( @@ -155,7 +155,7 @@ # .. event_type: org.openedx.learning.program.certificate.revoked.v1 # .. event_name: PROGRAM_CERTIFICATE_REVOKED # .. event_key_field: program_certificate.program.uuid -# .. event_description: Emit when a program certificate is revoked from a learner +# .. event_description: Emit when a program certificate is revoked from a learner. # .. event_data: ProgramCertificateData # .. event_trigger_repository: openedx/credentials PROGRAM_CERTIFICATE_REVOKED = OpenEdxPublicSignal( @@ -167,7 +167,7 @@ # .. event_type: org.openedx.learning.cohort_membership.changed.v1 # .. event_name: COHORT_MEMBERSHIP_CHANGED -# .. event_description: emitted when the user's cohort update is completed. +# .. event_description: Emitted when a user's cohort membership changes. # .. event_data: CohortData # .. event_trigger_repository: openedx/edx-platform COHORT_MEMBERSHIP_CHANGED = OpenEdxPublicSignal( @@ -180,8 +180,9 @@ # .. event_type: org.openedx.learning.discussions.configuration.changed.v1 # .. event_name: COURSE_DISCUSSIONS_CHANGED -# .. event_description: emitted when the configuration for a course's discussions changes in the course -# .. event_warning: This event is currently incompatible with the event bus, list/dict cannot be serialized yet +# .. event_description: Emitted when the configuration for a course's discussions changes in the course. +# .. event_warning: This event is currently incompatible with the event bus, list with complex types +# like ``List[DiscussionTopicContext]`` cannot be serialized yet. # .. event_data: CourseDiscussionConfigurationData # .. event_trigger_repository: openedx/edx-platform COURSE_DISCUSSIONS_CHANGED = OpenEdxPublicSignal( @@ -193,7 +194,7 @@ # .. event_type: org.openedx.learning.course.persistent_grade.summary.v1 # .. event_name: PERSISTENT_GRADE_SUMMARY_CHANGED -# .. event_description: emitted when a grade changes in the course +# .. event_description: Emitted when a course's persistent grade summary changes for a user. # .. event_data: PersistentCourseGradeData # .. event_trigger_repository: openedx/edx-platform PERSISTENT_GRADE_SUMMARY_CHANGED = OpenEdxPublicSignal( @@ -207,7 +208,7 @@ # .. event_type: org.openedx.learning.xblock.skill.verified.v1 # .. event_name: XBLOCK_SKILL_VERIFIED # .. event_key_field: xblock_info.usage_key -# .. event_description: Fired when an XBlock skill is verified. +# .. event_description: Emitted when an XBlock skill is verified. # .. event_data: XBlockSkillVerificationData # .. event_trigger_repository: openedx/xblock-skill-tagging XBLOCK_SKILL_VERIFIED = OpenEdxPublicSignal( @@ -219,9 +220,10 @@ # .. event_type: org.openedx.learning.user.notification.requested.v1 # .. event_name: USER_NOTIFICATION_REQUESTED -# .. event_description: Can be fired from apps to send user notifications. +# .. event_description: Can be emitted from apps to send user notifications. # .. event_data: UserNotificationSendListData -# .. event_warning: This event is currently incompatible with the event bus, list/dict cannot be serialized yet +# .. event_warning: This event is currently incompatible with the event bus, list without annotations +# are not serializable. # .. event_trigger_repository: openedx/edx-platform openedx/edx-ora2 USER_NOTIFICATION_REQUESTED = OpenEdxPublicSignal( event_type="org.openedx.learning.user.notification.requested.v1", @@ -317,10 +319,11 @@ # .. event_type: org.openedx.learning.forum.thread.created.v1 # .. event_name: FORUM_THREAD_CREATED -# .. event_description: Emitted when a new thread is created in a discussion +# .. event_description: Emitted when a new thread is created in a discussion. # .. event_data: DiscussionThreadData # .. event_trigger_repository: openedx/edx-platform -# .. event_warning: This event is currently incompatible with the event bus, list/dict cannot be serialized yet +# .. event_warning: This event is currently incompatible with the event bus, dict without annotations +# are not serializable. FORUM_THREAD_CREATED = OpenEdxPublicSignal( event_type="org.openedx.learning.forum.thread.created.v1", data={ @@ -330,10 +333,11 @@ # .. event_type: org.openedx.learning.forum.thread.response.created.v1 # .. event_name: FORUM_THREAD_RESPONSE_CREATED -# .. event_description: Emitted when a new response is added to a thread +# .. event_description: Emitted when a new response is added to a thread. # .. event_data: DiscussionThreadData # .. event_trigger_repository: openedx/edx-platform -# .. event_warning: This event is currently incompatible with the event bus, list/dict cannot be serialized yet +# .. event_warning: This event is currently incompatible with the event bus, dict without annotations +# are not serializable. FORUM_THREAD_RESPONSE_CREATED = OpenEdxPublicSignal( event_type="org.openedx.learning.forum.thread.response.created.v1", data={ @@ -343,10 +347,11 @@ # .. event_type: org.openedx.learning.forum.thread.response.comment.created.v1 # .. event_name: FORUM_RESPONSE_COMMENT_CREATED -# .. event_description: Emitted when a new comment is added to a response +# .. event_description: Emitted when a new comment is added to a response. # .. event_data: DiscussionThreadData # .. event_trigger_repository: openedx/edx-platform -# .. event_warning: This event is currently incompatible with the event bus, list/dict cannot be serialized yet +# .. event_warning: This event is currently incompatible with the event bus, dict without annotations +# are not serializable. FORUM_RESPONSE_COMMENT_CREATED = OpenEdxPublicSignal( event_type="org.openedx.learning.forum.thread.response.comment.created.v1", data={ @@ -357,10 +362,11 @@ # .. event_type: org.openedx.learning.course.notification.requested.v1 # .. event_name: COURSE_NOTIFICATION_REQUESTED -# .. event_description: Emitted when a notification is requested for a course +# .. event_description: Emitted when a notification is requested for a course. # .. event_data: CourseNotificationData # .. event_trigger_repository: openedx/edx-platform -# .. event_warning: This event is currently incompatible with the event bus, list/dict cannot be serialized yet +# .. event_warning: This event is currently incompatible with the event bus, dict without annotations +# are not serializable. COURSE_NOTIFICATION_REQUESTED = OpenEdxPublicSignal( event_type="org.openedx.learning.course.notification.requested.v1", data={ @@ -371,10 +377,10 @@ # .. event_type: org.openedx.learning.ora.submission.created.v1 # .. event_name: ORA_SUBMISSION_CREATED -# .. event_description: Emitted when a new ORA submission is created +# .. event_description: Emitted when a user submits an ORA assignment. # .. event_data: ORASubmissionData # .. event_trigger_repository: openedx/edx-ora2 -# .. event_warning: This event is currently incompatible with the event bus, list/dict cannot be serialized yet +# .. event_warning: This event is currently incompatible with the event bus, list[dict] cannot be serialized yet. ORA_SUBMISSION_CREATED = OpenEdxPublicSignal( event_type="org.openedx.learning.ora.submission.created.v1", data={ @@ -411,7 +417,7 @@ # .. event_type: org.openedx.learning.badge.awarded.v1 # .. event_name: BADGE_AWARDED -# .. event_description: Emit when a badge is awarded to a learner +# .. event_description: Emit when a badge is awarded to a learner. # .. event_data: BadgeData # .. event_trigger_repository: openedx/credentials BADGE_AWARDED = OpenEdxPublicSignal( @@ -424,7 +430,7 @@ # .. event_type: org.openedx.learning.badge.revoked.v1 # .. event_name: BADGE_REVOKED -# .. event_description: Emit when a badge is revoked for a learner +# .. event_description: Emit when a badge is revoked for a learner, # .. event_data: BadgeData # .. event_trigger_repository: openedx/credentials BADGE_REVOKED = OpenEdxPublicSignal( @@ -437,7 +443,7 @@ # .. event_type: org.openedx.learning.idv_attempt.created.v1 # .. event_name: IDV_ATTEMPT_CREATED -# .. event_description: Emitted when an IDV attempt is created +# .. event_description: Emitted when an IDV attempt is created. # .. event_data: VerificationAttemptData # .. event_trigger_repository: openedx/edx-platform IDV_ATTEMPT_CREATED = OpenEdxPublicSignal( @@ -450,7 +456,7 @@ # .. event_type: org.openedx.learning.idv_attempt.pending.v1 # .. event_name: IDV_ATTEMPT_PENDING -# .. event_description: Emitted when an IDV attempt is marked as pending +# .. event_description: Emitted when an IDV attempt is marked as pending. # .. event_data: VerificationAttemptData # .. event_trigger_repository: openedx/edx-platform IDV_ATTEMPT_PENDING = OpenEdxPublicSignal( @@ -463,7 +469,7 @@ # .. event_type: org.openedx.learning.idv_attempt.approved.v1 # .. event_name: IDV_ATTEMPT_APPROVED -# .. event_description: Emitted when an IDV attempt is approved +# .. event_description: Emitted when an IDV attempt is approved. # .. event_data: VerificationAttemptData # .. event_trigger_repository: openedx/edx-platform IDV_ATTEMPT_APPROVED = OpenEdxPublicSignal( @@ -476,7 +482,7 @@ # .. event_type: org.openedx.learning.idv_attempt.denied.v1 # .. event_name: IDV_ATTEMPT_DENIED -# .. event_description: Emitted when an IDV attempt is denied +# .. event_description: Emitted when an IDV attempt is denied. # .. event_data: VerificationAttemptData # .. event_trigger_repository: openedx/edx-platform IDV_ATTEMPT_DENIED = OpenEdxPublicSignal( diff --git a/openedx_events/tooling.py b/openedx_events/tooling.py index 7faa0380..f1faf4e9 100644 --- a/openedx_events/tooling.py +++ b/openedx_events/tooling.py @@ -81,8 +81,8 @@ def get_signal_by_type(cls, event_type): Arguments: event_type (str): name of the event. - Exceptions raised: - Raises KeyError if not found. + Raises: + Raises KeyError if the event is not found. """ return cls._mapping[event_type] @@ -95,21 +95,20 @@ def generate_signal_metadata(self, time=None): Arguments: time (datetime): (Optional) Timestamp when the event was sent with - UTC timezone. Defaults to current time in UTC. See OEP-41 for - details. + UTC timezone. Defaults to current time in UTC. See OEP-41 for more details. Example usage: >>> metadata = \ STUDENT_REGISTRATION_COMPLETED.generate_signal_metadata() attr.asdict(metadata) - { - 'event_type': '...learning.student.registration.completed.v1', - 'minorversion': 0, - 'time': '2021-06-09T14:12:45.320819Z', - 'source': 'openedx/lms/web', - 'sourcehost': 'edx.devstack.lms', - 'specversion': '1.0', - 'sourcelib: (0,1,0,), + >>> { + 'event_type': '...learning.student.registration.completed.v1', + 'minorversion': 0, + 'time': '2021-06-09T14:12:45.320819Z', + 'source': 'openedx/lms/web', + 'sourcehost': 'edx.devstack.lms', + 'specversion': '1.0', + 'sourcelib: (0,1,0,), } """ return EventsMetadata( @@ -128,9 +127,9 @@ def _send_event_with_metadata(self, metadata, send_robust=True, from_event_bus=F metadata (EventsMetadata): The metadata to be sent with the signal. send_robust (bool): Defaults to True. See Django signal docs. from_event_bus (bool): Defaults to False. If True, the signal is - being sent from the event bus. This is used to prevent infinite - loops when the event bus is consuming events. It should not be - used when sending events from the application. + being sent from the event bus. This is used to prevent infinite + loops when the event bus is consuming events. It should not be + used when sending events from the application. See ``send_event`` docstring for more details on its usage and behavior. """ @@ -186,16 +185,6 @@ def send_event(self, send_robust=True, time=None, **kwargs): """ Send events to all connected receivers. - Arguments: - send_robust (bool): Defaults to True. See Django signal docs. - time (datetime): (Optional - see note) Timestamp when the event was - sent with UTC timezone. For events requiring a DB create or - update, use the timestamp from the DB record. Defaults to - current time in UTC. This argument is optional for backward - compatability, but ideally would be explicitly set. See OEP-41 - for details. - kwargs: Data to be sent to the signal's receivers. - Used to send events just like Django signals are sent. In addition, some validations are executed on the arguments, and then generates relevant metadata that can be used for logging or debugging purposes. Besides this behavior, @@ -208,16 +197,26 @@ def send_event(self, send_robust=True, time=None, **kwargs): >>> STUDENT_REGISTRATION_COMPLETED.send_event( user=user_data, registration=registration_data, ) - [(, 'callback response')] + >>> [(, 'callback response')] + + Arguments: + send_robust (bool): Defaults to True. See Django signal docs. + time (datetime): (Optional - see note) Timestamp when the event was sent with UTC + timezone. For events requiring a DB create or update, use the timestamp from the DB + record. Defaults to current time in UTC. This argument is optional for backward + compatibility, but ideally would be explicitly set. See OEP-41 for details. + + Keyword Arguments: + kwargs: Data to be sent to the signal's receivers. The keys must match the attributes defined in + the event's data. Returns: - list: response of each receiver following the format - [(receiver, response), ... ]. Empty list if the event is disabled. + list: response of each receiver following the format [(receiver, response), ... ]. + The list is empty if the event is disabled. - Exceptions raised: - SenderValidationError: raised when there's a mismatch between - arguments passed to this method and arguments used to initialize - the event. + Raises: + SenderValidationError: raised when there's a mismatch between arguments passed + to this method and arguments used to initialize the event. """ metadata = self.generate_signal_metadata(time=time) return self._send_event_with_metadata(metadata=metadata, send_robust=send_robust, **kwargs) @@ -229,10 +228,10 @@ def send_event_with_custom_metadata( Send events to all connected receivers using the provided metadata. This method works exactly like ``send_event``, except it uses the given - event metadata rather than generating it. This is used by the - event bus consumer, where we want to recreate the metadata used - in the producer when resending the same signal on the consuming - side. + event metadata rather than generating it. This is used by the + event bus consumer, where we want to recreate the metadata used + in the producer when resending the same signal on the consuming + side. Arguments: metadata (EventsMetadata): The metadata to be sent with the signal. @@ -240,7 +239,6 @@ def send_event_with_custom_metadata( kwargs: Data to be sent to the signal's receivers. See ``send_event`` docstring for more details. - """ return self._send_event_with_metadata( metadata=metadata, send_robust=send_robust, from_event_bus=True, **kwargs diff --git a/openedx_events/utils.py b/openedx_events/utils.py index 56f5f3da..eaa0b9c3 100644 --- a/openedx_events/utils.py +++ b/openedx_events/utils.py @@ -68,13 +68,13 @@ def format_responses(obj, indent=1, width=80, depth=None, *, compact=False, sort ] Arguments: - obj (tuple): response object to be formatted. - indent (int): specifies the amount of indentation added to each recursive level. - width (int): desired output width. - depth (int): number of levels to represent. - compact (bool): when true, will format as many items as will fit within the width - on each output line. - sort_dicts (bool): dictionaries will be formatted with their keys sorted. + - obj (tuple): response object to be formatted. + - indent (int): specifies the amount of indentation added to each recursive level. + - width (int): desired output width. + - depth (int): number of levels to represent. + - compact (bool): when true, will format as many items as will fit within the width + on each output line. + - sort_dicts (bool): dictionaries will be formatted with their keys sorted. Same as in https://docs.python.org/3/library/pprint.html#pprint.PrettyPrinter