diff --git a/olx_importer/management/commands/load_components.py b/olx_importer/management/commands/load_components.py index 175175040..da51fbae5 100644 --- a/olx_importer/management/commands/load_components.py +++ b/olx_importer/management/commands/load_components.py @@ -140,7 +140,7 @@ def import_block_type(self, block_type_name, now): # , publish_log_entry): for xml_file_path in block_data_path.glob("*.xml"): components_found += 1 - local_key = xml_file_path.stem + component_code = xml_file_path.stem # Do some basic parsing of the content to see if it's even well # constructed enough to add (or whether we should skip/error on it). @@ -155,7 +155,7 @@ def import_block_type(self, block_type_name, now): # , publish_log_entry): _component, component_version = content_api.create_component_and_version( self.learning_package.id, component_type=block_type, - local_key=local_key, + component_code=component_code, title=display_name, created=now, created_by=None, diff --git a/src/openedx_content/applets/backup_restore/serializers.py b/src/openedx_content/applets/backup_restore/serializers.py index 549f3280f..8c5f8e955 100644 --- a/src/openedx_content/applets/backup_restore/serializers.py +++ b/src/openedx_content/applets/backup_restore/serializers.py @@ -6,6 +6,7 @@ from rest_framework import serializers from ..components import api as components_api +from ..components.models import ComponentType class LearningPackageSerializer(serializers.Serializer): # pylint: disable=abstract-method @@ -59,24 +60,55 @@ class EntityVersionSerializer(serializers.Serializer): # pylint: disable=abstra class ComponentSerializer(EntitySerializer): # pylint: disable=abstract-method """ Serializer for components. - Contains logic to convert entity_key to component_type and local_key. + Contains logic to convert entity_key to component_type and component_code. """ def validate(self, attrs): """ Custom validation logic: - parse the entity_key into (component_type, local_key). + parse the entity_key into (component_type, component_code). """ entity_key = attrs["key"] try: - component_type_obj, local_key = components_api.get_or_create_component_type_by_entity_key(entity_key) + component_type_obj, component_code = _get_or_create_component_type_by_entity_key(entity_key) attrs["component_type"] = component_type_obj - attrs["local_key"] = local_key + attrs["component_code"] = component_code except ValueError as exc: raise serializers.ValidationError({"key": str(exc)}) return attrs +def _get_or_create_component_type_by_entity_key(entity_key: str) -> tuple[ComponentType, str]: + """ + Get or create a ComponentType based on a full [entity].key string. + + The entity key is expected to be in the format + ``"{namespace}:{type_name}:{component_code}"``. This function will parse out + the ``namespace`` and ``type_name`` parts and use those to get or create the + ComponentType. + + Raises ValueError if the entity_key is not in the expected format. + + Historical note: In Ulmo, this function was part of the public API. This was + inappropriate because the exact format of entity_keys is just a convention + rather than something API callers should count on. That said, it is safe to + assume that in all "v1" archives, the components' entity keys are safe to + parse into (namespace, type, code). So, we have moved this parsing logic + from the public API to just this internal halper function. Future devs, + please do not make new external guarantees about the format of entity keys + (aka entity_refs). A future "v2" backup-restore format will drop this + assumption of parse-ability.. + """ + try: + namespace, type_name, component_code = entity_key.split(':', 2) + except ValueError as exc: + raise ValueError( + f"Invalid entity_key format: {entity_key!r}. " + "Expected format: '{namespace}:{type_name}:{component_code}'" + ) from exc + return components_api.get_or_create_component_type(namespace, type_name), component_code + + class ComponentVersionSerializer(EntityVersionSerializer): # pylint: disable=abstract-method """ Serializer for component versions. diff --git a/src/openedx_content/applets/backup_restore/zipper.py b/src/openedx_content/applets/backup_restore/zipper.py index 988daffe2..a1626a576 100644 --- a/src/openedx_content/applets/backup_restore/zipper.py +++ b/src/openedx_content/applets/backup_restore/zipper.py @@ -332,7 +332,7 @@ def create_zip(self, path: str) -> None: # v1/ # static/ - entity_filename = self.get_entity_toml_filename(entity.component.local_key) + entity_filename = self.get_entity_toml_filename(entity.component.component_code) component_root_folder = ( # Example: "entities/xblock.v1/html/" diff --git a/src/openedx_content/applets/components/api.py b/src/openedx_content/applets/components/api.py index 1c3ed3e40..0a70b8928 100644 --- a/src/openedx_content/applets/components/api.py +++ b/src/openedx_content/applets/components/api.py @@ -40,10 +40,10 @@ "create_next_component_version", "create_component_and_version", "get_component", - "get_component_by_key", + "get_component_by_code", "get_component_by_uuid", "get_component_version_by_uuid", - "component_exists_by_key", + "component_exists_by_code", "get_collection_components", "get_components", "create_component_version_media", @@ -79,27 +79,27 @@ def get_or_create_component_type_by_entity_key(entity_key: str) -> tuple[Compone Get or create a ComponentType based on a full entity key string. The entity key is expected to be in the format - ``"{namespace}:{type_name}:{local_key}"``. This function will parse out the - ``namespace`` and ``type_name`` parts and use those to get or create the + ``"{namespace}:{type_name}:{component_code}"``. This function will parse out + the ``namespace`` and ``type_name`` parts and use those to get or create the ComponentType. Raises ValueError if the entity_key is not in the expected format. """ try: - namespace, type_name, local_key = entity_key.split(':', 2) + namespace, type_name, component_code = entity_key.split(':', 2) except ValueError as exc: raise ValueError( f"Invalid entity_key format: {entity_key!r}. " - "Expected format: '{namespace}:{type_name}:{local_key}'" + "Expected format: '{namespace}:{type_name}:{component_code}'" ) from exc - return get_or_create_component_type(namespace, type_name), local_key + return get_or_create_component_type(namespace, type_name), component_code def create_component( learning_package_id: LearningPackage.ID, /, component_type: ComponentType, - local_key: str, + component_code: str, created: datetime, created_by: int | None, *, @@ -108,7 +108,7 @@ def create_component( """ Create a new Component (an entity like a Problem or Video) """ - key = f"{component_type.namespace}:{component_type.name}:{local_key}" + key = f"{component_type.namespace}:{component_type.name}:{component_code}" with atomic(): publishable_entity = publishing_api.create_publishable_entity( learning_package_id, @@ -121,7 +121,7 @@ def create_component( publishable_entity=publishable_entity, learning_package_id=learning_package_id, component_type=component_type, - local_key=local_key, + component_code=component_code, ) return component @@ -293,7 +293,7 @@ def create_component_and_version( # pylint: disable=too-many-positional-argumen learning_package_id: LearningPackage.ID, /, component_type: ComponentType, - local_key: str, + component_code: str, title: str, created: datetime, created_by: int | None = None, @@ -307,7 +307,7 @@ def create_component_and_version( # pylint: disable=too-many-positional-argumen component = create_component( learning_package_id, component_type, - local_key, + component_code, created, created_by, can_stand_alone=can_stand_alone, @@ -331,22 +331,22 @@ def get_component(component_id: Component.ID, /) -> Component: return Component.with_publishing_relations.get(pk=component_id) -def get_component_by_key( +def get_component_by_code( learning_package_id: LearningPackage.ID, /, namespace: str, type_name: str, - local_key: str, + component_code: str, ) -> Component: """ - Get a Component by its unique (namespace, type, local_key) tuple. + Get a Component by its unique (namespace, type, component_code) tuple. """ return Component.with_publishing_relations \ .get( learning_package_id=learning_package_id, component_type__namespace=namespace, component_type__name=type_name, - local_key=local_key, + component_code=component_code, ) @@ -366,12 +366,12 @@ def get_component_version_by_uuid(uuid: UUID) -> ComponentVersion: ) -def component_exists_by_key( +def component_exists_by_code( learning_package_id: LearningPackage.ID, /, namespace: str, type_name: str, - local_key: str + component_code: str ) -> bool: """ Return True/False for whether a Component exists. @@ -384,7 +384,7 @@ def component_exists_by_key( learning_package_id=learning_package_id, component_type__namespace=namespace, component_type__name=type_name, - local_key=local_key, + component_code=component_code, ) return True except Component.DoesNotExist: @@ -423,12 +423,12 @@ def get_components( # pylint: disable=too-many-positional-arguments if draft_title is not None: qset = qset.filter( Q(publishable_entity__draft__version__title__icontains=draft_title) | - Q(local_key__icontains=draft_title) + Q(component_code__icontains=draft_title) ) if published_title is not None: qset = qset.filter( Q(publishable_entity__published__version__title__icontains=published_title) | - Q(local_key__icontains=published_title) + Q(component_code__icontains=published_title) ) return qset diff --git a/src/openedx_content/applets/components/models.py b/src/openedx_content/applets/components/models.py index 6fbab2ba3..0fbeaccb0 100644 --- a/src/openedx_content/applets/components/models.py +++ b/src/openedx_content/applets/components/models.py @@ -22,7 +22,7 @@ from django.db import models from typing_extensions import deprecated -from openedx_django_lib.fields import case_sensitive_char_field, key_field +from openedx_django_lib.fields import case_sensitive_char_field, code_field, code_field_check, key_field from openedx_django_lib.managers import WithRelationsManager from ..media.models import Media @@ -119,9 +119,10 @@ class Component(PublishableEntityMixin): State Consistency ----------------- - The ``key`` field on Component's ``publishable_entity`` is dervied from the - ``component_type`` and ``local_key`` fields in this model. We don't support - changing the keys yet, but if we do, those values need to be kept in sync. + The ``key`` field on Component's ``publishable_entity`` is derived from the + ``component_type`` and ``component_code`` fields in this model. We don't + support changing the keys yet, but if we do, those values need to be kept + in sync. How build on this model ----------------------- @@ -176,37 +177,38 @@ def pk(self): # XBlock block_type, but we want it to be more flexible in the long term. component_type = models.ForeignKey(ComponentType, on_delete=models.PROTECT) - # local_key is an identifier that is local to the learning_package and - # component_type. The publishable.key should be calculated as a - # combination of component_type and local_key. - local_key = key_field() + # component_code is an identifier that is local to the learning_package and + # component_type. The publishable.key is derived from component_type and + # component_code. + component_code = code_field() class Meta: constraints = [ - # The combination of (component_type, local_key) is unique within - # a given LearningPackage. Note that this means it is possible to - # have two Components in the same LearningPackage to have the same - # local_key if the component_types are different. So for example, - # you could have a ProblemBlock and VideoBlock that both have the - # local_key "week_1". + # The combination of (component_type, component_code) is unique + # within a given LearningPackage. Note that this means it is + # possible to have two Components in the same LearningPackage with + # the same component_code if their component_types differ. For + # example, a ProblemBlock and VideoBlock could both have the + # component_code "week_1". models.UniqueConstraint( fields=[ "learning_package", "component_type", - "local_key", + "component_code", ], name="oel_component_uniq_lc_ct_lk", ), + code_field_check("component_code", name="oel_component_code_regex"), ] indexes = [ - # Global Component-Type/Local-Key Index: + # Global Component-Type/Component-Code Index: # * Search by the different Components fields across all Learning # Packages on the site. This would be a support-oriented tool # from Django Admin. models.Index( fields=[ "component_type", - "local_key", + "component_code", ], name="oel_component_idx_ct_lk", ), @@ -217,7 +219,7 @@ class Meta: verbose_name_plural = "Components" def __str__(self) -> str: - return f"{self.component_type.namespace}:{self.component_type.name}:{self.local_key}" + return f"{self.component_type.namespace}:{self.component_type.name}:{self.component_code}" class ComponentVersion(PublishableEntityVersionMixin): diff --git a/src/openedx_content/applets/publishing/models/publishable_entity.py b/src/openedx_content/applets/publishing/models/publishable_entity.py index 907b50248..c897b26cb 100644 --- a/src/openedx_content/applets/publishing/models/publishable_entity.py +++ b/src/openedx_content/applets/publishing/models/publishable_entity.py @@ -415,7 +415,7 @@ class VersioningHelper: learning_package_id=learning_package.id, namespace="xblock.v1", type="problem", - local_key="monty_hall", + component_code="monty_hall", title="Monty Hall Problem", created=now, created_by=None, diff --git a/src/openedx_content/management/commands/add_assets_to_component.py b/src/openedx_content/management/commands/add_assets_to_component.py index fc207e20a..ccd5b6f07 100644 --- a/src/openedx_content/management/commands/add_assets_to_component.py +++ b/src/openedx_content/management/commands/add_assets_to_component.py @@ -9,7 +9,7 @@ from django.core.management.base import BaseCommand -from ...api import create_next_component_version, get_component_by_key, get_learning_package_by_key +from ...api import create_next_component_version, get_component_by_code, get_learning_package_by_key class Command(BaseCommand): @@ -59,22 +59,22 @@ def handle(self, *args, **options): learning_package = get_learning_package_by_key(learning_package_key) # Parse something like: "xblock.v1:problem:area_of_circle_1" - namespace, type_name, local_key = component_key.split(":", 2) - component = get_component_by_key( - learning_package.id, namespace, type_name, local_key + namespace, type_name, component_code = component_key.split(":", 2) + component = get_component_by_code( + learning_package.id, namespace, type_name, component_code ) created = datetime.now(tz=timezone.utc) - local_keys_to_content_bytes = {} + media_path_to_content_bytes = {} for file_mapping in file_mappings: - local_key, file_path = file_mapping.split(":", 1) + media_path, file_path = file_mapping.split(":", 1) - local_keys_to_content_bytes[local_key] = pathlib.Path(file_path).read_bytes() if file_path else None + media_path_to_content_bytes[media_path] = pathlib.Path(file_path).read_bytes() if file_path else None next_version = create_next_component_version( component.id, - media_to_replace=local_keys_to_content_bytes, + media_to_replace=media_path_to_content_bytes, created=created, ) diff --git a/src/openedx_content/migrations/0009_rename_component_local_key_to_component_code.py b/src/openedx_content/migrations/0009_rename_component_local_key_to_component_code.py new file mode 100644 index 000000000..3879c55b6 --- /dev/null +++ b/src/openedx_content/migrations/0009_rename_component_local_key_to_component_code.py @@ -0,0 +1,74 @@ +""" +Rename Component.local_key -> Component.component_code and change from key_field to code_field. +""" +import re + +import django.core.validators +from django.db import migrations, models + +import openedx_django_lib.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('openedx_content', '0008_rename_collection_key_to_collection_code'), + ] + + operations = [ + # Drop old constraint and index (reference the old field name). + migrations.RemoveConstraint( + model_name='component', + name='oel_component_uniq_lc_ct_lk', + ), + migrations.RemoveIndex( + model_name='component', + name='oel_component_idx_ct_lk', + ), + # Rename the column. + migrations.RenameField( + model_name='component', + old_name='local_key', + new_name='component_code', + ), + # Change from key_field (max_length=500, no validator) to code_field + # (max_length=255, with regex validator). + migrations.AlterField( + model_name='component', + name='component_code', + field=openedx_django_lib.fields.MultiCollationCharField( + db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, + max_length=255, + validators=[ + django.core.validators.RegexValidator( + re.compile('^[a-zA-Z0-9_.-]+\\Z'), + 'Enter a valid "code name" consisting of letters, numbers, underscores, hyphens, or periods.', + 'invalid', + ), + ], + ), + ), + # Re-add constraint and index with the new field name. + migrations.AddConstraint( + model_name='component', + constraint=models.UniqueConstraint( + fields=('learning_package', 'component_type', 'component_code'), + name='oel_component_uniq_lc_ct_lk', + ), + ), + migrations.AddConstraint( + model_name='component', + constraint=models.CheckConstraint( + condition=django.db.models.lookups.Regex(models.F('component_code'), '^[a-zA-Z0-9_.-]+\\Z'), + name='oel_component_code_regex', + violation_error_message='Enter a valid "code name" consisting of letters, numbers, underscores, hyphens, or periods.', + ), + ), + migrations.AddIndex( + model_name='component', + index=models.Index( + fields=['component_type', 'component_code'], + name='oel_component_idx_ct_lk', + ), + ), + ] diff --git a/src/openedx_core/__init__.py b/src/openedx_core/__init__.py index b5fa534ec..c232e21a0 100644 --- a/src/openedx_core/__init__.py +++ b/src/openedx_core/__init__.py @@ -6,4 +6,4 @@ """ # The version for the entire repository -__version__ = "0.40.0" +__version__ = "0.41.0" diff --git a/tests/openedx_content/applets/backup_restore/test_backup.py b/tests/openedx_content/applets/backup_restore/test_backup.py index edafe3f66..6e9dc733c 100644 --- a/tests/openedx_content/applets/backup_restore/test_backup.py +++ b/tests/openedx_content/applets/backup_restore/test_backup.py @@ -69,7 +69,7 @@ def setUpTestData(cls): cls.published_component, _ = api.create_component_and_version( cls.learning_package.id, cls.problem_type, - local_key="my_published_example", + component_code="my_published_example", title="My published problem", created=cls.now, created_by=cls.user.id, @@ -80,7 +80,7 @@ def setUpTestData(cls): cls.published_component2, _ = api.create_component_and_version( cls.learning_package.id, cls.problem_type, - local_key="My_published_example", + component_code="My_published_example", title="My published problem 2", created=cls.now, created_by=cls.user.id, @@ -116,7 +116,7 @@ def setUpTestData(cls): cls.draft_component, _ = api.create_component_and_version( cls.learning_package.id, cls.html_type, - local_key="my_draft_example", + component_code="my_draft_example", title="My draft html", created=cls.now, created_by=cls.user.id, @@ -315,7 +315,7 @@ def test_queries_n_plus_problem(self): api.create_component_and_version( self.learning_package.id, self.problem_type, - local_key="my_published_example2", + component_code="my_published_example2", title="My published problem 2", created=self.now, created_by=self.user.id, diff --git a/tests/openedx_content/applets/collections/test_api.py b/tests/openedx_content/applets/collections/test_api.py index 42e4f1638..daf839cfa 100644 --- a/tests/openedx_content/applets/collections/test_api.py +++ b/tests/openedx_content/applets/collections/test_api.py @@ -279,7 +279,7 @@ def setUpTestData(cls) -> None: cls.published_component, _ = api.create_component_and_version( cls.learning_package.id, cls.problem_type, - local_key="my_published_example", + component_code="my_published_example", title="My published problem", created=cls.now, created_by=cls.user.id, @@ -294,7 +294,7 @@ def setUpTestData(cls) -> None: cls.draft_component, _ = api.create_component_and_version( cls.learning_package.id, cls.html_type, - local_key="my_draft_example", + component_code="my_draft_example", title="My draft html", created=cls.now, created_by=cls.user.id, diff --git a/tests/openedx_content/applets/components/test_api.py b/tests/openedx_content/applets/components/test_api.py index 74f482090..c46746061 100644 --- a/tests/openedx_content/applets/components/test_api.py +++ b/tests/openedx_content/applets/components/test_api.py @@ -54,14 +54,14 @@ def publish_component(self, component: Component): ), ) - def create_component(self, *, title: str = "Test Component", key: str = "component:1") -> tuple[ + def create_component(self, *, title: str = "Test Component", component_code: str = "component_1") -> tuple[ Component, ComponentVersion ]: """ Helper method to quickly create a component """ return components_api.create_component_and_version( self.learning_package.id, component_type=self.problem_type, - local_key=key, + component_code=component_code, title=title, created=self.now, created_by=None, @@ -86,7 +86,7 @@ def test_component_num_queries(self) -> None: component, _version = components_api.create_component_and_version( self.learning_package.id, component_type=self.problem_type, - local_key="Query Counting", + component_code="Query_Counting", title="Querying Counting Problem", created=self.now, created_by=None, @@ -131,7 +131,7 @@ def setUpTestData(cls) -> None: cls.published_problem, _version = components_api.create_component_and_version( cls.learning_package.id, component_type=v2_problem_type, - local_key="pp_lk", + component_code="pp_lk", title="Published Problem", created=cls.now, created_by=None, @@ -139,7 +139,7 @@ def setUpTestData(cls) -> None: cls.published_html, _version = components_api.create_component_and_version( cls.learning_package.id, component_type=cls.html_type, - local_key="ph_lk", + component_code="ph_lk", title="Published HTML", created=cls.now, created_by=None, @@ -153,7 +153,7 @@ def setUpTestData(cls) -> None: cls.unpublished_problem, _version = components_api.create_component_and_version( cls.learning_package.id, component_type=v2_problem_type, - local_key="upp_lk", + component_code="upp_lk", title="Unpublished Problem", created=cls.now, created_by=None, @@ -161,7 +161,7 @@ def setUpTestData(cls) -> None: cls.unpublished_html, _version = components_api.create_component_and_version( cls.learning_package.id, component_type=cls.html_type, - local_key="uph_lk", + component_code="uph_lk", title="Unpublished HTML", created=cls.now, created_by=None, @@ -172,7 +172,7 @@ def setUpTestData(cls) -> None: cls.deleted_video, _version = components_api.create_component_and_version( cls.learning_package.id, component_type=cls.video_type, - local_key="dv_lk", + component_code="dv_lk", title="Deleted Video", created=cls.now, created_by=None, @@ -324,14 +324,14 @@ def setUpTestData(cls) -> None: cls.problem = components_api.create_component( cls.learning_package.id, component_type=cls.problem_type, - local_key='my_component', + component_code='my_component', created=cls.now, created_by=None, ) cls.html = components_api.create_component( cls.learning_package.id, component_type=cls.html_type, - local_key='my_component', + component_code='my_component', created=cls.now, created_by=None, can_stand_alone=False, @@ -343,46 +343,46 @@ def test_simple_get(self): components_api.get_component(-1) def test_publishing_entity_key_convention(self): - """Our mapping convention is {namespace}:{component_type}:{local_key}""" + """Our mapping convention is {namespace}:{component_type}:{component_code}""" assert self.problem.key == "xblock.v1:problem:my_component" def test_stand_alone_flag(self): """Check if can_stand_alone flag is set""" - component = components_api.get_component_by_key( + component = components_api.get_component_by_code( self.learning_package.id, namespace='xblock.v1', type_name='html', - local_key='my_component', + component_code='my_component', ) assert not component.publishable_entity.can_stand_alone - def test_get_by_key(self): - assert self.html == components_api.get_component_by_key( + def test_get_by_code(self): + assert self.html == components_api.get_component_by_code( self.learning_package.id, namespace='xblock.v1', type_name='html', - local_key='my_component', + component_code='my_component', ) with self.assertRaises(ObjectDoesNotExist): - components_api.get_component_by_key( + components_api.get_component_by_code( self.learning_package.id, namespace='xblock.v1', type_name='video', # 'video' doesn't match anything we have - local_key='my_component', + component_code='my_component', ) - def test_exists_by_key(self): - assert components_api.component_exists_by_key( + def test_exists_by_code(self): + assert components_api.component_exists_by_code( self.learning_package.id, namespace='xblock.v1', type_name='problem', - local_key='my_component', + component_code='my_component', ) - assert not components_api.component_exists_by_key( + assert not components_api.component_exists_by_code( self.learning_package.id, namespace='xblock.v1', type_name='problem', - local_key='not_my_component', + component_code='not_my_component', ) @@ -399,7 +399,7 @@ def setUpTestData(cls) -> None: cls.problem = components_api.create_component( cls.learning_package.id, component_type=cls.problem_type, - local_key='my_component', + component_code='my_component', created=cls.now, created_by=None, ) @@ -659,7 +659,7 @@ def setUpTestData(cls) -> None: cls.published_problem, _ = components_api.create_component_and_version( cls.learning_package.id, component_type=v2_problem_type, - local_key="pp_lk", + component_code="pp_lk", title="Published Problem", created=cls.now, created_by=None, @@ -697,26 +697,26 @@ class TestComponentTypeUtils(TestCase): """ def test_get_or_create_component_type_by_entity_key_creates_new(self): - comp_type, local_key = components_api.get_or_create_component_type_by_entity_key( + comp_type, component_code = components_api.get_or_create_component_type_by_entity_key( "video:youtube:abcd1234" ) assert isinstance(comp_type, ComponentType) assert comp_type.namespace == "video" assert comp_type.name == "youtube" - assert local_key == "abcd1234" + assert component_code == "abcd1234" assert ComponentType.objects.count() == 1 def test_get_or_create_component_type_by_entity_key_existing(self): ComponentType.objects.create(namespace="video", name="youtube") - comp_type, local_key = components_api.get_or_create_component_type_by_entity_key( + comp_type, component_code = components_api.get_or_create_component_type_by_entity_key( "video:youtube:efgh5678" ) assert comp_type.namespace == "video" assert comp_type.name == "youtube" - assert local_key == "efgh5678" + assert component_code == "efgh5678" assert ComponentType.objects.count() == 1 def test_get_or_create_component_type_by_entity_key_invalid_format(self): diff --git a/tests/openedx_content/applets/components/test_assets.py b/tests/openedx_content/applets/components/test_assets.py index a9c378681..f146b3298 100644 --- a/tests/openedx_content/applets/components/test_assets.py +++ b/tests/openedx_content/applets/components/test_assets.py @@ -59,7 +59,7 @@ def setUpTestData(cls) -> None: cls.component, cls.component_version = components_api.create_component_and_version( cls.learning_package.id, component_type=cls.problem_type, - local_key="my_problem", + component_code="my_problem", title="My Problem", created=cls.now, created_by=None, diff --git a/tests/openedx_content/applets/components/test_models.py b/tests/openedx_content/applets/components/test_models.py index bdcdea725..e029bed17 100644 --- a/tests/openedx_content/applets/components/test_models.py +++ b/tests/openedx_content/applets/components/test_models.py @@ -51,7 +51,7 @@ def test_latest_version(self) -> None: component, component_version = create_component_and_version( self.learning_package.id, component_type=self.problem_type, - local_key="monty_hall", + component_code="monty_hall", title="Monty Hall Problem", created=self.now, created_by=None, @@ -82,7 +82,7 @@ def test_last_publish_log(self): component_with_changes, _ = create_component_and_version( self.learning_package.id, component_type=self.problem_type, - local_key="with_changes", + component_code="with_changes", title="Component with changes v1", created=self.now, created_by=None, @@ -92,7 +92,7 @@ def test_last_publish_log(self): component_with_no_changes, _ = create_component_and_version( self.learning_package.id, component_type=self.problem_type, - local_key="with_no_changes", + component_code="with_no_changes", title="Component with no changes v1", created=self.now, created_by=None, diff --git a/tests/openedx_content/applets/sections/test_api.py b/tests/openedx_content/applets/sections/test_api.py index 3e873915a..f4807640b 100644 --- a/tests/openedx_content/applets/sections/test_api.py +++ b/tests/openedx_content/applets/sections/test_api.py @@ -22,11 +22,11 @@ def setUp(self) -> None: """Create some potential desdendants for use in these tests.""" super().setUp() self.component_1, self.component_1_v1 = self.create_component( - key="component_1", + component_code="component_1", title="Great-grandchild component", ) self.component_2, self.component_2_v1 = self.create_component( - key="component_2", + component_code="component_2", title="Great-grandchild component", ) common_args: dict[str, Any] = { diff --git a/tests/openedx_content/applets/subsections/test_api.py b/tests/openedx_content/applets/subsections/test_api.py index e4bc871e2..74c7685b4 100644 --- a/tests/openedx_content/applets/subsections/test_api.py +++ b/tests/openedx_content/applets/subsections/test_api.py @@ -21,11 +21,11 @@ class SubsectionsTestCase(ComponentTestCase): def setUp(self) -> None: super().setUp() self.component_1, self.component_1_v1 = self.create_component( - key="Query Counting", + component_code="Query_Counting", title="Querying Counting Problem", ) self.component_2, self.component_2_v1 = self.create_component( - key="Query Counting (2)", + component_code="Query_Counting_2", title="Querying Counting Problem (2)", ) self.unit_1, self.unit_1_v1 = content_api.create_unit_and_version( @@ -156,7 +156,7 @@ def test_create_subsection_with_invalid_children(self): # Try adding a Component to a Subsection with pytest.raises( ValidationError, - match='The entity "xblock.v1:problem:Query Counting" cannot be added to a "subsection" container.', + match='The entity "xblock.v1:problem:Query_Counting" cannot be added to a "subsection" container.', ) as err: content_api.create_next_subsection_version( subsection, @@ -175,7 +175,7 @@ def test_create_subsection_with_invalid_children(self): # (not just `create_next_subsection_version()`) with pytest.raises( ValidationError, - match='The entity "xblock.v1:problem:Query Counting" cannot be added to a "subsection" container.', + match='The entity "xblock.v1:problem:Query_Counting" cannot be added to a "subsection" container.', ): self.create_subsection_with_units([self.component_1], key="unit:key3", title="Unit 3") diff --git a/tests/openedx_content/applets/units/test_api.py b/tests/openedx_content/applets/units/test_api.py index 6ca67fdf0..364970a8a 100644 --- a/tests/openedx_content/applets/units/test_api.py +++ b/tests/openedx_content/applets/units/test_api.py @@ -22,11 +22,11 @@ class UnitsTestCase(ComponentTestCase): def setUp(self) -> None: super().setUp() self.component_1, self.component_1_v1 = self.create_component( - key="Query Counting", + component_code="Query_Counting", title="Querying Counting Problem", ) self.component_2, self.component_2_v1 = self.create_component( - key="Query Counting (2)", + component_code="Query_Counting_2", title="Querying Counting Problem (2)", )