From 6995de84955d7e0e0417982e17dbf526538c1f2a Mon Sep 17 00:00:00 2001 From: Jillian Vogel Date: Thu, 3 Apr 2025 20:50:30 +1030 Subject: [PATCH 1/3] refactor!: use LibraryCollectionLocator in LibraryCollectionData The library_key can be inferred from the collection_key --- openedx_events/content_authoring/data.py | 8 +++---- .../event_bus/avro/custom_serializers.py | 22 ++++++++++++++++++- ..._library+collection+created+v1_schema.avsc | 4 ---- ..._library+collection+deleted+v1_schema.avsc | 4 ---- ..._library+collection+updated+v1_schema.avsc | 4 ---- .../event_bus/avro/tests/test_avro.py | 6 ++++- 6 files changed, 29 insertions(+), 19 deletions(-) diff --git a/openedx_events/content_authoring/data.py b/openedx_events/content_authoring/data.py index 3f13887b..afb17eda 100644 --- a/openedx_events/content_authoring/data.py +++ b/openedx_events/content_authoring/data.py @@ -12,7 +12,7 @@ import attr from opaque_keys.edx.keys import CourseKey, UsageKey -from opaque_keys.edx.locator import LibraryLocatorV2, LibraryUsageLocatorV2 +from opaque_keys.edx.locator import LibraryCollectionLocator, LibraryLocatorV2, LibraryUsageLocatorV2 @attr.s(frozen=True) @@ -218,14 +218,12 @@ class LibraryCollectionData: Data related to a library collection that has changed. Attributes: - library_key (LibraryLocatorV2): a key that represents a content library. - collection_key (str): identifies the collection within the library's learning package + collection_key (LibraryCollectionLocator): 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. """ - library_key = attr.ib(type=LibraryLocatorV2) - collection_key = attr.ib(type=str) + collection_key = attr.ib(type=LibraryCollectionLocator) background = attr.ib(type=bool, default=False) diff --git a/openedx_events/event_bus/avro/custom_serializers.py b/openedx_events/event_bus/avro/custom_serializers.py index d3503011..9235884e 100644 --- a/openedx_events/event_bus/avro/custom_serializers.py +++ b/openedx_events/event_bus/avro/custom_serializers.py @@ -8,7 +8,7 @@ from ccx_keys.locator import CCXLocator from opaque_keys.edx.keys import CourseKey, UsageKey -from opaque_keys.edx.locator import LibraryLocatorV2, LibraryUsageLocatorV2 +from opaque_keys.edx.locator import LibraryCollectionLocator, LibraryLocatorV2, LibraryUsageLocatorV2 from openedx_events.event_bus.avro.types import PYTHON_TYPE_TO_AVRO_MAPPING @@ -112,6 +112,25 @@ def deserialize(data: str): return UsageKey.from_string(data) +class LibraryCollectionLocatorAvroSerializer(BaseCustomTypeAvroSerializer): + """ + CustomTypeAvroSerializer for LibraryCollectionLocator class. + """ + + cls = LibraryCollectionLocator + field_type = PYTHON_TYPE_TO_AVRO_MAPPING[str] + + @staticmethod + def serialize(obj) -> str: + """Serialize obj into string.""" + return str(obj) + + @staticmethod + def deserialize(data: str): + """Deserialize string into obj.""" + return LibraryCollectionLocator.from_string(data) + + class LibraryLocatorV2AvroSerializer(BaseCustomTypeAvroSerializer): """ CustomTypeAvroSerializer for LibraryLocatorV2 class. @@ -175,6 +194,7 @@ def deserialize(data: str): CourseKeyAvroSerializer, CcxCourseLocatorAvroSerializer, DatetimeAvroSerializer, + LibraryCollectionLocatorAvroSerializer, LibraryLocatorV2AvroSerializer, LibraryUsageLocatorV2AvroSerializer, UsageKeyAvroSerializer, diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+created+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+created+v1_schema.avsc index 0c47f299..a66ddb6c 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+created+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+created+v1_schema.avsc @@ -9,10 +9,6 @@ "name": "LibraryCollectionData", "type": "record", "fields": [ - { - "name": "library_key", - "type": "string" - }, { "name": "collection_key", "type": "string" diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+deleted+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+deleted+v1_schema.avsc index da95e9e0..5f7062be 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+deleted+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+deleted+v1_schema.avsc @@ -9,10 +9,6 @@ "name": "LibraryCollectionData", "type": "record", "fields": [ - { - "name": "library_key", - "type": "string" - }, { "name": "collection_key", "type": "string" diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+updated+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+updated+v1_schema.avsc index 7f581cd5..c78990f1 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+updated+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+collection+updated+v1_schema.avsc @@ -9,10 +9,6 @@ "name": "LibraryCollectionData", "type": "record", "fields": [ - { - "name": "library_key", - "type": "string" - }, { "name": "collection_key", "type": "string" diff --git a/openedx_events/event_bus/avro/tests/test_avro.py b/openedx_events/event_bus/avro/tests/test_avro.py index 528e7ffe..b01fa95b 100644 --- a/openedx_events/event_bus/avro/tests/test_avro.py +++ b/openedx_events/event_bus/avro/tests/test_avro.py @@ -11,7 +11,7 @@ from fastavro.repository.base import SchemaRepositoryError from fastavro.schema import load_schema from opaque_keys.edx.keys import CourseKey, UsageKey -from opaque_keys.edx.locator import LibraryLocatorV2, LibraryUsageLocatorV2 +from opaque_keys.edx.locator import LibraryCollectionLocator, LibraryLocatorV2, LibraryUsageLocatorV2 from openedx_events.event_bus.avro.deserializer import AvroSignalDeserializer, deserialize_bytes_to_event_data from openedx_events.event_bus.avro.serializer import AvroSignalSerializer, serialize_event_data_to_bytes @@ -109,6 +109,7 @@ def generate_test_event_data_for_data_type(data_type): # pragma: no cover UsageKey: UsageKey.from_string( "block-v1:edx+DemoX+Demo_course+type@video+block@UaEBjyMjcLW65gaTXggB93WmvoxGAJa0JeHRrDThk", ), + LibraryCollectionLocator: LibraryCollectionLocator.from_string('lib-collection:MITx:reallyhardproblems:col1'), LibraryLocatorV2: LibraryLocatorV2.from_string('lib:MITx:reallyhardproblems'), LibraryUsageLocatorV2: LibraryUsageLocatorV2.from_string('lb:MITx:reallyhardproblems:problem:problem1'), List[int]: [1, 2, 3], @@ -125,6 +126,9 @@ def generate_test_event_data_for_data_type(data_type): # pragma: no cover "block-v1:edx+DemoX+Demo_course+type@video+block@UaEBjyMjcLW65gaTXggB93WmvoxGAJa0JeHRrDThk", )}, dict[str, LibraryLocatorV2]: {'key': LibraryLocatorV2.from_string('lib:MITx:reallyhardproblems')}, + dict[str, LibraryCollectionLocator]: { + 'key': LibraryCollectionLocator.from_string('lib-collection:MITx:reallyhardproblems:col1'), + }, dict[str, LibraryUsageLocatorV2]: { 'key': LibraryUsageLocatorV2.from_string('lb:MITx:reallyhardproblems:problem:problem1'), }, From 6c537aa47d0a6268b6e366d222c44c7b14a145eb Mon Sep 17 00:00:00 2001 From: Jillian Vogel Date: Fri, 4 Apr 2025 13:25:23 +1030 Subject: [PATCH 2/3] refactor!: use LibraryContainerLocator in LibraryContainerData The library_key can be inferred from the container_key --- openedx_events/content_authoring/data.py | 13 +++++---- .../event_bus/avro/custom_serializers.py | 27 ++++++++++++++++++- ...t_library+container+created+v1_schema.avsc | 4 --- ...t_library+container+deleted+v1_schema.avsc | 4 --- ...t_library+container+updated+v1_schema.avsc | 4 --- .../event_bus/avro/tests/test_avro.py | 13 ++++++++- 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/openedx_events/content_authoring/data.py b/openedx_events/content_authoring/data.py index afb17eda..d431fc63 100644 --- a/openedx_events/content_authoring/data.py +++ b/openedx_events/content_authoring/data.py @@ -12,7 +12,12 @@ import attr from opaque_keys.edx.keys import CourseKey, UsageKey -from opaque_keys.edx.locator import LibraryCollectionLocator, LibraryLocatorV2, LibraryUsageLocatorV2 +from opaque_keys.edx.locator import ( + LibraryCollectionLocator, + LibraryContainerLocator, + LibraryLocatorV2, + LibraryUsageLocatorV2, +) @attr.s(frozen=True) @@ -233,12 +238,10 @@ class LibraryContainerData: Data related to a library container that has changed. Attributes: - library_key (LibraryLocatorV2): a key that represents a content library. - container_key (str): identifies the container within the library's learning package (e.g. unit, section) + container_key (LibraryContainerLocator): identifies the container (e.g. unit, section) 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. """ - library_key = attr.ib(type=LibraryLocatorV2) - container_key = attr.ib(type=str) + container_key = attr.ib(type=LibraryContainerLocator) background = attr.ib(type=bool, default=False) diff --git a/openedx_events/event_bus/avro/custom_serializers.py b/openedx_events/event_bus/avro/custom_serializers.py index 9235884e..e786036b 100644 --- a/openedx_events/event_bus/avro/custom_serializers.py +++ b/openedx_events/event_bus/avro/custom_serializers.py @@ -8,7 +8,12 @@ from ccx_keys.locator import CCXLocator from opaque_keys.edx.keys import CourseKey, UsageKey -from opaque_keys.edx.locator import LibraryCollectionLocator, LibraryLocatorV2, LibraryUsageLocatorV2 +from opaque_keys.edx.locator import ( + LibraryCollectionLocator, + LibraryContainerLocator, + LibraryLocatorV2, + LibraryUsageLocatorV2, +) from openedx_events.event_bus.avro.types import PYTHON_TYPE_TO_AVRO_MAPPING @@ -131,6 +136,25 @@ def deserialize(data: str): return LibraryCollectionLocator.from_string(data) +class LibraryContainerLocatorAvroSerializer(BaseCustomTypeAvroSerializer): + """ + CustomTypeAvroSerializer for LibraryContainerLocator class. + """ + + cls = LibraryContainerLocator + field_type = PYTHON_TYPE_TO_AVRO_MAPPING[str] + + @staticmethod + def serialize(obj) -> str: + """Serialize obj into string.""" + return str(obj) + + @staticmethod + def deserialize(data: str): + """Deserialize string into obj.""" + return LibraryContainerLocator.from_string(data) + + class LibraryLocatorV2AvroSerializer(BaseCustomTypeAvroSerializer): """ CustomTypeAvroSerializer for LibraryLocatorV2 class. @@ -195,6 +219,7 @@ def deserialize(data: str): CcxCourseLocatorAvroSerializer, DatetimeAvroSerializer, LibraryCollectionLocatorAvroSerializer, + LibraryContainerLocatorAvroSerializer, LibraryLocatorV2AvroSerializer, LibraryUsageLocatorV2AvroSerializer, UsageKeyAvroSerializer, diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+created+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+created+v1_schema.avsc index ef16b300..c3a0bb50 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+created+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+created+v1_schema.avsc @@ -9,10 +9,6 @@ "name": "LibraryContainerData", "type": "record", "fields": [ - { - "name": "library_key", - "type": "string" - }, { "name": "container_key", "type": "string" diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+deleted+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+deleted+v1_schema.avsc index 5218e795..4fd7bdd6 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+deleted+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+deleted+v1_schema.avsc @@ -9,10 +9,6 @@ "name": "LibraryContainerData", "type": "record", "fields": [ - { - "name": "library_key", - "type": "string" - }, { "name": "container_key", "type": "string" diff --git a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+updated+v1_schema.avsc b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+updated+v1_schema.avsc index 231e57ee..b966d837 100644 --- a/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+updated+v1_schema.avsc +++ b/openedx_events/event_bus/avro/tests/schemas/org+openedx+content_authoring+content_library+container+updated+v1_schema.avsc @@ -9,10 +9,6 @@ "name": "LibraryContainerData", "type": "record", "fields": [ - { - "name": "library_key", - "type": "string" - }, { "name": "container_key", "type": "string" diff --git a/openedx_events/event_bus/avro/tests/test_avro.py b/openedx_events/event_bus/avro/tests/test_avro.py index b01fa95b..884760d8 100644 --- a/openedx_events/event_bus/avro/tests/test_avro.py +++ b/openedx_events/event_bus/avro/tests/test_avro.py @@ -11,7 +11,12 @@ from fastavro.repository.base import SchemaRepositoryError from fastavro.schema import load_schema from opaque_keys.edx.keys import CourseKey, UsageKey -from opaque_keys.edx.locator import LibraryCollectionLocator, LibraryLocatorV2, LibraryUsageLocatorV2 +from opaque_keys.edx.locator import ( + LibraryCollectionLocator, + LibraryContainerLocator, + LibraryLocatorV2, + LibraryUsageLocatorV2, +) from openedx_events.event_bus.avro.deserializer import AvroSignalDeserializer, deserialize_bytes_to_event_data from openedx_events.event_bus.avro.serializer import AvroSignalSerializer, serialize_event_data_to_bytes @@ -110,6 +115,9 @@ def generate_test_event_data_for_data_type(data_type): # pragma: no cover "block-v1:edx+DemoX+Demo_course+type@video+block@UaEBjyMjcLW65gaTXggB93WmvoxGAJa0JeHRrDThk", ), LibraryCollectionLocator: LibraryCollectionLocator.from_string('lib-collection:MITx:reallyhardproblems:col1'), + LibraryContainerLocator: LibraryContainerLocator.from_string( + 'lct:MITx:reallyhardproblems:unit:test-container', + ), LibraryLocatorV2: LibraryLocatorV2.from_string('lib:MITx:reallyhardproblems'), LibraryUsageLocatorV2: LibraryUsageLocatorV2.from_string('lb:MITx:reallyhardproblems:problem:problem1'), List[int]: [1, 2, 3], @@ -129,6 +137,9 @@ def generate_test_event_data_for_data_type(data_type): # pragma: no cover dict[str, LibraryCollectionLocator]: { 'key': LibraryCollectionLocator.from_string('lib-collection:MITx:reallyhardproblems:col1'), }, + dict[str, LibraryContainerLocator]: { + 'key': LibraryContainerLocator.from_string('lct:MITx:reallyhardproblems:unit:test-container'), + }, dict[str, LibraryUsageLocatorV2]: { 'key': LibraryUsageLocatorV2.from_string('lb:MITx:reallyhardproblems:problem:problem1'), }, From d8014fe5dbd8ed66810c2ad574eb48e4015515e5 Mon Sep 17 00:00:00 2001 From: Jillian Vogel Date: Fri, 4 Apr 2025 14:25:56 +1030 Subject: [PATCH 3/3] chore: bumps major package version with breaking change in CHANGELOG --- CHANGELOG.rst | 7 +++++++ openedx_events/__init__.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ce5724e5..bff7ab40 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -16,6 +16,13 @@ Change Log Unreleased __________ +[10.0.0] - 2024-04-04 +--------------------- +Changed +~~~~~~~ +* **Breaking change**: LibraryCollectionData now takes only a LibraryCollectionLocator. +* **Breaking change**: LibraryContainerData now takes only a LibraryContainerLocator. + [9.20.0] - 2025-03-15 --------------------- diff --git a/openedx_events/__init__.py b/openedx_events/__init__.py index d03641ae..ac7f15c7 100644 --- a/openedx_events/__init__.py +++ b/openedx_events/__init__.py @@ -5,4 +5,4 @@ more information about the project. """ -__version__ = "9.20.0" +__version__ = "10.0.0"