From 152b54c8ea4422d35123e99a381a2ff18f930a8c Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Sun, 28 Dec 2025 00:57:48 -0500 Subject: [PATCH 01/13] temp: basic setup stuff --- .gitignore | 9 +++++++-- projects/dev.py | 25 +++++++++++-------------- projects/urls.py | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 6123dd4cf..faa881b9a 100644 --- a/.gitignore +++ b/.gitignore @@ -75,7 +75,12 @@ venv/ !.vscode/settings.json.example # Media files (for uploads) -media/ +/media/ # Media files generated during test runs -test_media/ +/test_media/ + +# uv stuff +.lock +CACHEDIR.TAG +pyvenv.cfg diff --git a/projects/dev.py b/projects/dev.py index 1b3b42f47..4a05c2f46 100644 --- a/projects/dev.py +++ b/projects/dev.py @@ -31,19 +31,19 @@ "django.contrib.admin", "django.contrib.admindocs", # Learning Core Apps - "openedx_learning.apps.authoring.collections.apps.CollectionsConfig", - "openedx_learning.apps.authoring.components.apps.ComponentsConfig", - "openedx_learning.apps.authoring.contents.apps.ContentsConfig", - "openedx_learning.apps.authoring.publishing.apps.PublishingConfig", - "openedx_learning.apps.authoring.sections.apps.SectionsConfig", - "openedx_learning.apps.authoring.subsections.apps.SubsectionsConfig", - "openedx_learning.apps.authoring.units.apps.UnitsConfig", - "openedx_learning.apps.authoring.backup_restore.apps.BackupRestoreConfig", + "openedx_learning.apps.authoring.collections", + "openedx_learning.apps.authoring.components", + "openedx_learning.apps.authoring.contents", + "openedx_learning.apps.authoring.publishing", + "openedx_learning.apps.authoring.sections", + "openedx_learning.apps.authoring.subsections", + "openedx_learning.apps.authoring.units", + "openedx_learning.apps.authoring.backup_restore", # Learning Contrib Apps - "openedx_learning.contrib.media_server.apps.MediaServerConfig", + # "openedx_learning.contrib.media_server.apps.MediaServerConfig", # Apps that don't belong in this repo in the long term, but are here to make # testing/iteration easier until the APIs stabilize. - "olx_importer.apps.OLXImporterConfig", + # "olx_importer.apps.OLXImporterConfig", # REST API "rest_framework", @@ -51,9 +51,6 @@ 'rules.apps.AutodiscoverRulesConfig', # Tagging Core Apps "openedx_tagging.core.tagging.apps.TaggingConfig", - - # Debugging - "debug_toolbar", ) AUTHENTICATION_BACKENDS = [ @@ -62,7 +59,7 @@ ] MIDDLEWARE = [ - "debug_toolbar.middleware.DebugToolbarMiddleware", +# "debug_toolbar.middleware.DebugToolbarMiddleware", "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", diff --git a/projects/urls.py b/projects/urls.py index 583b004b4..082ff2113 100644 --- a/projects/urls.py +++ b/projects/urls.py @@ -9,5 +9,5 @@ path("admin/", admin.site.urls), path("media_server/", include("openedx_learning.contrib.media_server.urls")), path("tagging/rest_api/", include("openedx_tagging.core.tagging.urls")), - path('__debug__/', include('debug_toolbar.urls')), + # path('__debug__/', include('debug_toolbar.urls')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) From a647afcdacd13c7ed3adab4a335d6330852c8b48 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Mon, 29 Dec 2025 02:02:16 -0500 Subject: [PATCH 02/13] refactor: create initial authoring migration --- openedx_learning/apps/authoring/admin.py | 8 + openedx_learning/apps/authoring/apps.py | 22 + .../apps/authoring/backup_restore/apps.py | 12 - .../apps/authoring/collections/apps.py | 15 - .../apps/authoring/collections/models.py | 2 + .../apps/authoring/components/apps.py | 24 - .../apps/authoring/components/models.py | 6 + .../apps/authoring/contents/apps.py | 15 - .../apps/authoring/migrations/0001_initial.py | 630 ++++++++++++++++++ .../apps/authoring/migrations/__init__.py | 0 openedx_learning/apps/authoring/models.py | 8 + .../apps/authoring/publishing/apps.py | 25 - .../authoring/publishing/models/container.py | 5 + .../authoring/publishing/models/draft_log.py | 6 + .../publishing/models/entity_list.py | 5 + .../publishing/models/learning_package.py | 1 + .../publishing/models/publish_log.py | 4 + .../publishing/models/publishable_entity.py | 3 + .../apps/authoring/sections/apps.py | 25 - .../apps/authoring/subsections/apps.py | 25 - openedx_learning/apps/authoring/units/apps.py | 25 - projects/dev.py | 20 +- 22 files changed, 712 insertions(+), 174 deletions(-) create mode 100644 openedx_learning/apps/authoring/admin.py create mode 100644 openedx_learning/apps/authoring/apps.py delete mode 100644 openedx_learning/apps/authoring/backup_restore/apps.py delete mode 100644 openedx_learning/apps/authoring/collections/apps.py delete mode 100644 openedx_learning/apps/authoring/components/apps.py delete mode 100644 openedx_learning/apps/authoring/contents/apps.py create mode 100644 openedx_learning/apps/authoring/migrations/0001_initial.py create mode 100644 openedx_learning/apps/authoring/migrations/__init__.py create mode 100644 openedx_learning/apps/authoring/models.py delete mode 100644 openedx_learning/apps/authoring/publishing/apps.py delete mode 100644 openedx_learning/apps/authoring/sections/apps.py delete mode 100644 openedx_learning/apps/authoring/subsections/apps.py delete mode 100644 openedx_learning/apps/authoring/units/apps.py diff --git a/openedx_learning/apps/authoring/admin.py b/openedx_learning/apps/authoring/admin.py new file mode 100644 index 000000000..ff67ae96f --- /dev/null +++ b/openedx_learning/apps/authoring/admin.py @@ -0,0 +1,8 @@ +from .backup_restore.admin import * +from .collections.admin import * +from .components.admin import * +from .contents.admin import * +from .publishing.admin import * +from .sections.admin import * +from .subsections.admin import * +from .units.admin import * \ No newline at end of file diff --git a/openedx_learning/apps/authoring/apps.py b/openedx_learning/apps/authoring/apps.py new file mode 100644 index 000000000..26bd01d24 --- /dev/null +++ b/openedx_learning/apps/authoring/apps.py @@ -0,0 +1,22 @@ +from django.apps import AppConfig + +class AuthoringConfig(AppConfig): + name = "openedx_learning.apps.authoring" + verbose_name = "Learning Core > Authoring" + default_auto_field = "django.db.models.BigAutoField" + label = "oel_authoring" + + def ready(self): + from .publishing.api import register_publishable_models + + from .components.models import Component, ComponentVersion + from .publishing.models import Container, ContainerVersion + from .sections.models import Section, SectionVersion + from .subsections.models import Subsection, SubsectionVersion + from .units.models import Unit, UnitVersion + + register_publishable_models(Component, ComponentVersion) + register_publishable_models(Container, ContainerVersion) + register_publishable_models(Section, SectionVersion) + register_publishable_models(Subsection, SubsectionVersion) + register_publishable_models(Unit, UnitVersion) diff --git a/openedx_learning/apps/authoring/backup_restore/apps.py b/openedx_learning/apps/authoring/backup_restore/apps.py deleted file mode 100644 index 7aa3f022b..000000000 --- a/openedx_learning/apps/authoring/backup_restore/apps.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -Backup/Restore application initialization. -""" - -from django.apps import AppConfig - - -class BackupRestoreConfig(AppConfig): - name = 'openedx_learning.apps.authoring.backup_restore' - verbose_name = "Learning Core > Authoring > Backup Restore" - default_auto_field = 'django.db.models.BigAutoField' - label = "oel_backup_restore" diff --git a/openedx_learning/apps/authoring/collections/apps.py b/openedx_learning/apps/authoring/collections/apps.py deleted file mode 100644 index b1ca50c49..000000000 --- a/openedx_learning/apps/authoring/collections/apps.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -Django metadata for the Collections Django application. -""" -from django.apps import AppConfig - - -class CollectionsConfig(AppConfig): - """ - Configuration for the Collections Django application. - """ - - name = "openedx_learning.apps.authoring.collections" - verbose_name = "Learning Core > Authoring > Collections" - default_auto_field = "django.db.models.BigAutoField" - label = "oel_collections" diff --git a/openedx_learning/apps/authoring/collections/models.py b/openedx_learning/apps/authoring/collections/models.py index 731f2cb73..48a0bb072 100644 --- a/openedx_learning/apps/authoring/collections/models.py +++ b/openedx_learning/apps/authoring/collections/models.py @@ -168,6 +168,7 @@ class Collection(models.Model): ) class Meta: + db_table = 'oel_collections_collection' verbose_name_plural = "Collections" constraints = [ # Keys are unique within a given LearningPackage. @@ -222,6 +223,7 @@ class CollectionPublishableEntity(models.Model): ) class Meta: + db_table = 'oel_collections_collectionpublishableentity' constraints = [ # Prevent race conditions from making multiple rows associating the # same Collection to the same Entity. diff --git a/openedx_learning/apps/authoring/components/apps.py b/openedx_learning/apps/authoring/components/apps.py deleted file mode 100644 index 591e60f6c..000000000 --- a/openedx_learning/apps/authoring/components/apps.py +++ /dev/null @@ -1,24 +0,0 @@ -""" -Django metadata for the Components Django application. -""" -from django.apps import AppConfig - - -class ComponentsConfig(AppConfig): - """ - Configuration for the Components Django application. - """ - - name = "openedx_learning.apps.authoring.components" - verbose_name = "Learning Core > Authoring > Components" - default_auto_field = "django.db.models.BigAutoField" - label = "oel_components" - - def ready(self) -> None: - """ - Register Component and ComponentVersion. - """ - from ..publishing.api import register_publishable_models # pylint: disable=import-outside-toplevel - from .models import Component, ComponentVersion # pylint: disable=import-outside-toplevel - - register_publishable_models(Component, ComponentVersion) diff --git a/openedx_learning/apps/authoring/components/models.py b/openedx_learning/apps/authoring/components/models.py index b53077637..d84e42bba 100644 --- a/openedx_learning/apps/authoring/components/models.py +++ b/openedx_learning/apps/authoring/components/models.py @@ -76,6 +76,9 @@ class ComponentType(models.Model): def __str__(self) -> str: return f"{self.namespace}:{self.name}" + class Meta: + db_table = 'oel_components_componenttype' + class Component(PublishableEntityMixin): """ @@ -155,6 +158,7 @@ class Component(PublishableEntityMixin): local_key = key_field() class Meta: + db_table = 'oel_components_component' constraints = [ # The combination of (component_type, local_key) is unique within # a given LearningPackage. Note that this means it is possible to @@ -217,6 +221,7 @@ class ComponentVersion(PublishableEntityVersionMixin): ) class Meta: + db_table = 'oel_components_componentversion' verbose_name = "Component Version" verbose_name_plural = "Component Versions" @@ -248,6 +253,7 @@ class ComponentVersionContent(models.Model): key = key_field(db_column="_key") class Meta: + db_table = 'oel_components_componentversioncontent' constraints = [ # Uniqueness is only by ComponentVersion and key. If for some reason # a ComponentVersion wants to associate the same piece of content diff --git a/openedx_learning/apps/authoring/contents/apps.py b/openedx_learning/apps/authoring/contents/apps.py deleted file mode 100644 index 3c23bd4f5..000000000 --- a/openedx_learning/apps/authoring/contents/apps.py +++ /dev/null @@ -1,15 +0,0 @@ -""" -Django metadata for the Contents Django application. -""" -from django.apps import AppConfig - - -class ContentsConfig(AppConfig): - """ - Configuration for the Contents Django application. - """ - - name = "openedx_learning.apps.authoring.contents" - verbose_name = "Learning Core > Authoring > Contents" - default_auto_field = "django.db.models.BigAutoField" - label = "oel_contents" diff --git a/openedx_learning/apps/authoring/migrations/0001_initial.py b/openedx_learning/apps/authoring/migrations/0001_initial.py new file mode 100644 index 000000000..5848c05bb --- /dev/null +++ b/openedx_learning/apps/authoring/migrations/0001_initial.py @@ -0,0 +1,630 @@ +# Generated by Django 5.2.9 on 2025-12-29 06:47 + +import django.core.validators +import django.db.models.deletion +import openedx_learning.lib.fields +import openedx_learning.lib.validators +import uuid +from django.conf import settings +from django.db import migrations, models +from django.db.migrations.operations.special import SeparateDatabaseAndState + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + SeparateDatabaseAndState( + database_operations=[], + state_operations=[ + migrations.CreateModel( + name='PublishableEntity', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), + ('key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, db_column='_key', max_length=500)), + ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('can_stand_alone', models.BooleanField(default=True, help_text='Set to True when created independently, False when created as part of a container.')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Publishable Entity', + 'verbose_name_plural': 'Publishable Entities', + 'db_table': 'oel_publishing_publishableentity', + }, + ), + migrations.CreateModel( + name='ComponentType', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('namespace', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, max_length=100)), + ('name', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, max_length=100)), + ], + options={ + 'db_table': 'oel_components_componenttype', + }, + ), + migrations.CreateModel( + name='PublishableEntityVersion', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), + ('title', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, default='', max_length=500)), + ('version_num', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1)])), + ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ('entity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='versions', to='oel_authoring.publishableentity')), + ], + options={ + 'verbose_name': 'Publishable Entity Version', + 'verbose_name_plural': 'Publishable Entity Versions', + 'db_table': 'oel_publishing_publishableentityversion', + }, + ), + migrations.CreateModel( + name='Content', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('size', models.PositiveBigIntegerField(validators=[django.core.validators.MaxValueValidator(50000000)])), + ('hash_digest', models.CharField(editable=False, max_length=40)), + ('has_file', models.BooleanField()), + ('text', openedx_learning.lib.fields.MultiCollationTextField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=50000, null=True)), + ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ], + options={ + 'verbose_name': 'Content', + 'verbose_name_plural': 'Contents', + }, + ), + migrations.CreateModel( + name='EntityList', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + options={ + 'db_table': 'oel_publishing_entitylist', + }, + ), + migrations.CreateModel( + name='LearningPackage', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), + ('key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, db_column='_key', max_length=500)), + ('title', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=500)), + ('description', openedx_learning.lib.fields.MultiCollationTextField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, default='', max_length=10000)), + ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ], + options={ + 'verbose_name': 'Learning Package', + 'verbose_name_plural': 'Learning Packages', + 'db_table': 'oel_publishing_learningpackage', + }, + ), + migrations.CreateModel( + name='MediaType', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('type', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=127)), + ('sub_type', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=127)), + ('suffix', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=127)), + ], + ), + migrations.CreateModel( + name='PublishableEntityVersionDependency', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + options={ + 'db_table': 'oel_publishing_publishableentityversiondependency', + }, + ), + migrations.CreateModel( + name='PublishLog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), + ('message', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, default='', max_length=500)), + ('published_at', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ], + options={ + 'verbose_name': 'Publish Log', + 'verbose_name_plural': 'Publish Logs', + 'db_table': 'oel_publishing_publishlog', + }, + ), + migrations.CreateModel( + name='PublishLogRecord', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('dependencies_hash_digest', models.CharField(blank=True, default='', editable=False, max_length=8)), + ], + options={ + 'verbose_name': 'Publish Log Record', + 'verbose_name_plural': 'Publish Log Records', + 'db_table': 'oel_publishing_publishlogrecord', + }, + ), + migrations.CreateModel( + name='PublishSideEffect', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ], + options={ + 'verbose_name': 'Publish Side Effect', + 'verbose_name_plural': 'Publish Side Effects', + 'db_table': 'oel_publishing_publishsideeffect', + }, + ), + migrations.CreateModel( + name='Collection', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False)), + ('key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, db_column='_key', max_length=500)), + ('title', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, help_text='The title of the collection.', max_length=500)), + ('description', openedx_learning.lib.fields.MultiCollationTextField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, default='', help_text='Provides extra information for the user about this collection.', max_length=10000)), + ('enabled', models.BooleanField(default=True, help_text='Disabled collections are "soft deleted", and should be re-enabled before use, or be deleted.')), + ('created', models.DateTimeField(auto_now_add=True, validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('modified', models.DateTimeField(auto_now=True, validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name_plural': 'Collections', + 'db_table': 'oel_collections_collection', + }, + ), + migrations.CreateModel( + name='Component', + fields=[ + ('publishable_entity', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_authoring.publishableentity')), + ('local_key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, max_length=500)), + ], + options={ + 'verbose_name': 'Component', + 'verbose_name_plural': 'Components', + 'db_table': 'oel_components_component', + }, + ), + migrations.CreateModel( + name='Container', + fields=[ + ('publishable_entity', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_authoring.publishableentity')), + ], + options={ + 'db_table': 'oel_publishing_container', + }, + ), + migrations.CreateModel( + name='Draft', + fields=[ + ('entity', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_authoring.publishableentity')), + ], + options={ + 'db_table': 'oel_publishing_draft', + }, + ), + migrations.CreateModel( + name='Published', + fields=[ + ('entity', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_authoring.publishableentity')), + ], + options={ + 'verbose_name': 'Published Entity', + 'verbose_name_plural': 'Published Entities', + 'db_table': 'oel_publishing_published', + }, + ), + migrations.CreateModel( + name='CollectionPublishableEntity', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True, validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('collection', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.collection')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ('entity', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.publishableentity')), + ], + options={ + 'db_table': 'oel_collections_collectionpublishableentity', + }, + ), + migrations.AddField( + model_name='collection', + name='entities', + field=models.ManyToManyField(related_name='collections', through='oel_authoring.CollectionPublishableEntity', to='oel_authoring.publishableentity'), + ), + migrations.CreateModel( + name='ComponentVersion', + fields=[ + ('publishable_entity_version', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_authoring.publishableentityversion')), + ], + options={ + 'verbose_name': 'Component Version', + 'verbose_name_plural': 'Component Versions', + 'db_table': 'oel_components_componentversion', + }, + ), + migrations.CreateModel( + name='ContainerVersion', + fields=[ + ('publishable_entity_version', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_authoring.publishableentityversion')), + ], + options={ + 'db_table': 'oel_publishing_containerversion', + }, + ), + migrations.CreateModel( + name='ComponentVersionContent', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, db_column='_key', max_length=500)), + ('content', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.content')), + ], + options={ + 'db_table': 'oel_components_componentversioncontent', + }, + ), + migrations.CreateModel( + name='DraftChangeLog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), + ('changed_at', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), + ('changed_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'Draft Change Log', + 'verbose_name_plural': 'Draft Change Logs', + 'db_table': 'oel_publishing_draftchangelog', + }, + ), + migrations.CreateModel( + name='DraftChangeLogRecord', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('dependencies_hash_digest', models.CharField(blank=True, default='', editable=False, max_length=8)), + ('draft_change_log', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='records', to='oel_authoring.draftchangelog')), + ('entity', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.publishableentity')), + ('new_version', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.publishableentityversion')), + ('old_version', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, related_name='+', to='oel_authoring.publishableentityversion')), + ], + options={ + 'verbose_name': 'Draft Change Log Record', + 'verbose_name_plural': 'Draft Change Log Records', + 'db_table': 'oel_publishing_draftchangelogrecord', + }, + ), + migrations.CreateModel( + name='DraftSideEffect', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cause', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='causes', to='oel_authoring.draftchangelogrecord')), + ('effect', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='affected_by', to='oel_authoring.draftchangelogrecord')), + ], + options={ + 'verbose_name': 'Draft Side Effect', + 'verbose_name_plural': 'Draft Side Effects', + 'db_table': 'oel_publishing_draftsideeffect', + }, + ), + migrations.CreateModel( + name='EntityListRow', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('order_num', models.PositiveIntegerField()), + ('entity', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.publishableentity')), + ('entity_list', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.entitylist')), + ('entity_version', models.ForeignKey(null=True, on_delete=django.db.models.deletion.RESTRICT, related_name='+', to='oel_authoring.publishableentityversion')), + ], + options={ + 'db_table': 'oel_publishing_entitylistrow', + 'ordering': ['order_num'], + }, + ), + migrations.AddField( + model_name='publishableentity', + name='learning_package', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publishable_entities', to='oel_authoring.learningpackage'), + ), + migrations.AddConstraint( + model_name='learningpackage', + constraint=models.UniqueConstraint(fields=('key',), name='oel_publishing_lp_uniq_key'), + ), + migrations.AddField( + model_name='draftchangelog', + name='learning_package', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), + ), + migrations.AddField( + model_name='content', + name='learning_package', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), + ), + migrations.AddField( + model_name='collection', + name='learning_package', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), + ), + migrations.AddConstraint( + model_name='mediatype', + constraint=models.UniqueConstraint(fields=('type', 'sub_type', 'suffix'), name='oel_contents_uniq_t_st_sfx'), + ), + migrations.AddField( + model_name='content', + name='media_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='oel_authoring.mediatype'), + ), + migrations.AddField( + model_name='publishableentityversiondependency', + name='referenced_entity', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.publishableentity'), + ), + migrations.AddField( + model_name='publishableentityversiondependency', + name='referring_version', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.publishableentityversion'), + ), + migrations.AddField( + model_name='publishableentityversion', + name='dependencies', + field=models.ManyToManyField(related_name='affects', through='oel_authoring.PublishableEntityVersionDependency', to='oel_authoring.publishableentity'), + ), + migrations.AddField( + model_name='publishlog', + name='learning_package', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), + ), + migrations.AddField( + model_name='publishlog', + name='published_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='publishlogrecord', + name='entity', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.publishableentity'), + ), + migrations.AddField( + model_name='publishlogrecord', + name='new_version', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.publishableentityversion'), + ), + migrations.AddField( + model_name='publishlogrecord', + name='old_version', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, related_name='+', to='oel_authoring.publishableentityversion'), + ), + migrations.AddField( + model_name='publishlogrecord', + name='publish_log', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='records', to='oel_authoring.publishlog'), + ), + migrations.AddField( + model_name='publishsideeffect', + name='cause', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='causes', to='oel_authoring.publishlogrecord'), + ), + migrations.AddField( + model_name='publishsideeffect', + name='effect', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='affected_by', to='oel_authoring.publishlogrecord'), + ), + migrations.AddField( + model_name='component', + name='component_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='oel_authoring.componenttype'), + ), + migrations.AddField( + model_name='component', + name='learning_package', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.learningpackage'), + ), + migrations.CreateModel( + name='Section', + fields=[ + ('container', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_authoring.container')), + ], + options={ + 'abstract': False, + }, + bases=('oel_authoring.container',), + ), + migrations.CreateModel( + name='Subsection', + fields=[ + ('container', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_authoring.container')), + ], + options={ + 'abstract': False, + }, + bases=('oel_authoring.container',), + ), + migrations.CreateModel( + name='Unit', + fields=[ + ('container', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_authoring.container')), + ], + options={ + 'abstract': False, + }, + bases=('oel_authoring.container',), + ), + migrations.AddField( + model_name='draft', + name='draft_log_record', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_authoring.draftchangelogrecord'), + ), + migrations.AddField( + model_name='draft', + name='version', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.publishableentityversion'), + ), + migrations.AddField( + model_name='published', + name='publish_log_record', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.publishlogrecord'), + ), + migrations.AddField( + model_name='published', + name='version', + field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_authoring.publishableentityversion'), + ), + migrations.AddConstraint( + model_name='collectionpublishableentity', + constraint=models.UniqueConstraint(fields=('collection', 'entity'), name='oel_collections_cpe_uniq_col_ent'), + ), + migrations.AddField( + model_name='componentversioncontent', + name='component_version', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_authoring.componentversion'), + ), + migrations.AddField( + model_name='componentversion', + name='component', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='versions', to='oel_authoring.component'), + ), + migrations.AddField( + model_name='componentversion', + name='contents', + field=models.ManyToManyField(related_name='component_versions', through='oel_authoring.ComponentVersionContent', to='oel_authoring.content'), + ), + migrations.CreateModel( + name='SectionVersion', + fields=[ + ('container_version', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_authoring.containerversion')), + ], + options={ + 'abstract': False, + }, + bases=('oel_authoring.containerversion',), + ), + migrations.CreateModel( + name='SubsectionVersion', + fields=[ + ('container_version', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_authoring.containerversion')), + ], + options={ + 'abstract': False, + }, + bases=('oel_authoring.containerversion',), + ), + migrations.CreateModel( + name='UnitVersion', + fields=[ + ('container_version', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_authoring.containerversion')), + ], + options={ + 'abstract': False, + }, + bases=('oel_authoring.containerversion',), + ), + migrations.AddField( + model_name='containerversion', + name='container', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='versions', to='oel_authoring.container'), + ), + migrations.AddField( + model_name='containerversion', + name='entity_list', + field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='container_versions', to='oel_authoring.entitylist'), + ), + migrations.AddIndex( + model_name='draftchangelogrecord', + index=models.Index(fields=['entity', '-draft_change_log'], name='oel_dlr_idx_entity_rdcl'), + ), + migrations.AddConstraint( + model_name='draftchangelogrecord', + constraint=models.UniqueConstraint(fields=('draft_change_log', 'entity'), name='oel_dlr_uniq_dcl'), + ), + migrations.AddConstraint( + model_name='draftsideeffect', + constraint=models.UniqueConstraint(fields=('cause', 'effect'), name='oel_pub_dse_uniq_c_e'), + ), + migrations.AddConstraint( + model_name='entitylistrow', + constraint=models.UniqueConstraint(fields=('entity_list', 'order_num'), name='oel_publishing_elist_row_order'), + ), + migrations.AddIndex( + model_name='publishableentity', + index=models.Index(fields=['key'], name='oel_pub_ent_idx_key'), + ), + migrations.AddIndex( + model_name='publishableentity', + index=models.Index(fields=['learning_package', '-created'], name='oel_pub_ent_idx_lp_rcreated'), + ), + migrations.AddConstraint( + model_name='publishableentity', + constraint=models.UniqueConstraint(fields=('learning_package', 'key'), name='oel_pub_ent_uniq_lp_key'), + ), + migrations.AddIndex( + model_name='collection', + index=models.Index(fields=['learning_package', 'title'], name='oel_collect_learnin_dfaf89_idx'), + ), + migrations.AddConstraint( + model_name='collection', + constraint=models.UniqueConstraint(fields=('learning_package', 'key'), name='oel_coll_uniq_lp_key'), + ), + migrations.AddIndex( + model_name='content', + index=models.Index(fields=['learning_package', '-size'], name='oel_content_idx_lp_rsize'), + ), + migrations.AddConstraint( + model_name='content', + constraint=models.UniqueConstraint(fields=('learning_package', 'media_type', 'hash_digest'), name='oel_content_uniq_lc_media_type_hash_digest'), + ), + migrations.AddConstraint( + model_name='publishableentityversiondependency', + constraint=models.UniqueConstraint(fields=('referring_version', 'referenced_entity'), name='oel_pevd_uniq_rv_re'), + ), + migrations.AddIndex( + model_name='publishableentityversion', + index=models.Index(fields=['entity', '-created'], name='oel_pv_idx_entity_rcreated'), + ), + migrations.AddIndex( + model_name='publishableentityversion', + index=models.Index(fields=['title'], name='oel_pv_idx_title'), + ), + migrations.AddConstraint( + model_name='publishableentityversion', + constraint=models.UniqueConstraint(fields=('entity', 'version_num'), name='oel_pv_uniq_entity_version_num'), + ), + migrations.AddIndex( + model_name='publishlogrecord', + index=models.Index(fields=['entity', '-publish_log'], name='oel_plr_idx_entity_rplr'), + ), + migrations.AddConstraint( + model_name='publishlogrecord', + constraint=models.UniqueConstraint(fields=('publish_log', 'entity'), name='oel_plr_uniq_pl_publishable'), + ), + migrations.AddConstraint( + model_name='publishsideeffect', + constraint=models.UniqueConstraint(fields=('cause', 'effect'), name='oel_pub_pse_uniq_c_e'), + ), + migrations.AddIndex( + model_name='component', + index=models.Index(fields=['component_type', 'local_key'], name='oel_component_idx_ct_lk'), + ), + migrations.AddConstraint( + model_name='component', + constraint=models.UniqueConstraint(fields=('learning_package', 'component_type', 'local_key'), name='oel_component_uniq_lc_ct_lk'), + ), + migrations.AddIndex( + model_name='componentversioncontent', + index=models.Index(fields=['content', 'component_version'], name='oel_cvcontent_c_cv'), + ), + migrations.AddIndex( + model_name='componentversioncontent', + index=models.Index(fields=['component_version', 'content'], name='oel_cvcontent_cv_d'), + ), + migrations.AddConstraint( + model_name='componentversioncontent', + constraint=models.UniqueConstraint(fields=('component_version', 'key'), name='oel_cvcontent_uniq_cv_key'), + ), + ] + ) + ] diff --git a/openedx_learning/apps/authoring/migrations/__init__.py b/openedx_learning/apps/authoring/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/openedx_learning/apps/authoring/models.py b/openedx_learning/apps/authoring/models.py new file mode 100644 index 000000000..5965c8b1c --- /dev/null +++ b/openedx_learning/apps/authoring/models.py @@ -0,0 +1,8 @@ +from .backup_restore.models import * +from .collections.models import * +from .components.models import * +from .contents.models import * +from .publishing.models import * +from .sections.models import * +from .subsections.models import * +from .units.models import * diff --git a/openedx_learning/apps/authoring/publishing/apps.py b/openedx_learning/apps/authoring/publishing/apps.py deleted file mode 100644 index d3aefd8a6..000000000 --- a/openedx_learning/apps/authoring/publishing/apps.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -publishing Django application initialization. -""" - -from django.apps import AppConfig - - -class PublishingConfig(AppConfig): - """ - Configuration for the publishing Django application. - """ - - name = "openedx_learning.apps.authoring.publishing" - verbose_name = "Learning Core > Authoring > Publishing" - default_auto_field = "django.db.models.BigAutoField" - label = "oel_publishing" - - def ready(self): - """ - Register Container and ContainerVersion. - """ - from .api import register_publishable_models # pylint: disable=import-outside-toplevel - from .models import Container, ContainerVersion # pylint: disable=import-outside-toplevel - - register_publishable_models(Container, ContainerVersion) diff --git a/openedx_learning/apps/authoring/publishing/models/container.py b/openedx_learning/apps/authoring/publishing/models/container.py index e34bb6a7e..fc008dd3a 100644 --- a/openedx_learning/apps/authoring/publishing/models/container.py +++ b/openedx_learning/apps/authoring/publishing/models/container.py @@ -23,6 +23,8 @@ class Container(PublishableEntityMixin): PublishLog and Containers that were affected in a publish because their child elements were published. """ + class Meta: + db_table = 'oel_publishing_container' class ContainerVersion(PublishableEntityVersionMixin): @@ -68,3 +70,6 @@ def clean(self): super().clean() if self.container_id != self.publishable_entity_version.entity.container.pk: # pylint: disable=no-member raise ValidationError("Inconsistent foreign keys to Container") + + class Meta: + db_table = 'oel_publishing_containerversion' diff --git a/openedx_learning/apps/authoring/publishing/models/draft_log.py b/openedx_learning/apps/authoring/publishing/models/draft_log.py index ed3eb8731..89b58ecbb 100644 --- a/openedx_learning/apps/authoring/publishing/models/draft_log.py +++ b/openedx_learning/apps/authoring/publishing/models/draft_log.py @@ -70,6 +70,9 @@ class Draft(models.Model): null=True, ) + class Meta: + db_table = 'oel_publishing_draft' + @property def log_record(self): return self.draft_log_record @@ -140,6 +143,7 @@ class DraftChangeLog(models.Model): ) class Meta: + db_table = 'oel_publishing_draftchangelog' verbose_name = _("Draft Change Log") verbose_name_plural = _("Draft Change Logs") @@ -274,6 +278,7 @@ class DraftChangeLogRecord(models.Model): dependencies_hash_digest = hash_field(blank=True, default='', max_length=8) class Meta: + db_table = 'oel_publishing_draftchangelogrecord' constraints = [ # A PublishableEntity can have only one DraftLogRecord per DraftLog. # You can't simultaneously change the same thing in two different @@ -379,6 +384,7 @@ class DraftSideEffect(models.Model): ) class Meta: + db_table = 'oel_publishing_draftsideeffect' constraints = [ # Duplicate entries for cause & effect are just redundant. This is # here to guard against weird bugs that might introduce this state. diff --git a/openedx_learning/apps/authoring/publishing/models/entity_list.py b/openedx_learning/apps/authoring/publishing/models/entity_list.py index 252ea2e37..d3da8d8ca 100644 --- a/openedx_learning/apps/authoring/publishing/models/entity_list.py +++ b/openedx_learning/apps/authoring/publishing/models/entity_list.py @@ -18,6 +18,10 @@ class EntityList(models.Model): anonymous in a sense–they're pointed to by ContainerVersions and other models, rather than being looked up by their own identifiers. """ + + class Meta: + db_table = 'oel_publishing_entitylist' + @cached_property def rows(self): """ @@ -79,6 +83,7 @@ def is_unpinned(self): return self.entity_version_id is None class Meta: + db_table = 'oel_publishing_entitylistrow' ordering = ["order_num"] constraints = [ # If (entity_list, order_num) is not unique, it likely indicates a race condition - so force uniqueness. diff --git a/openedx_learning/apps/authoring/publishing/models/learning_package.py b/openedx_learning/apps/authoring/publishing/models/learning_package.py index 3ff5bb4bd..8d3c68003 100644 --- a/openedx_learning/apps/authoring/publishing/models/learning_package.py +++ b/openedx_learning/apps/authoring/publishing/models/learning_package.py @@ -61,6 +61,7 @@ def __str__(self): return f"{self.key}" class Meta: + db_table = 'oel_publishing_learningpackage' constraints = [ # LearningPackage keys must be globally unique. This is something # that might be relaxed in the future if this system were to be diff --git a/openedx_learning/apps/authoring/publishing/models/publish_log.py b/openedx_learning/apps/authoring/publishing/models/publish_log.py index d3bc1241f..a5a72702b 100644 --- a/openedx_learning/apps/authoring/publishing/models/publish_log.py +++ b/openedx_learning/apps/authoring/publishing/models/publish_log.py @@ -57,6 +57,7 @@ class PublishLog(models.Model): ) class Meta: + db_table = 'oel_publishing_publishlog' verbose_name = "Publish Log" verbose_name_plural = "Publish Logs" @@ -112,6 +113,7 @@ class PublishLogRecord(models.Model): dependencies_hash_digest = hash_field(blank=True, default='', max_length=8) class Meta: + db_table = 'oel_publishing_publishlogrecord' constraints = [ # A Publishable can have only one PublishLogRecord per PublishLog. # You can't simultaneously publish two different versions of the @@ -186,6 +188,7 @@ def log_record(self): return self.publish_log_record class Meta: + db_table = 'oel_publishing_published' verbose_name = "Published Entity" verbose_name_plural = "Published Entities" @@ -224,6 +227,7 @@ class PublishSideEffect(models.Model): ) class Meta: + db_table = 'oel_publishing_publishsideeffect' constraints = [ # Duplicate entries for cause & effect are just redundant. This is # here to guard against weird bugs that might introduce this state. diff --git a/openedx_learning/apps/authoring/publishing/models/publishable_entity.py b/openedx_learning/apps/authoring/publishing/models/publishable_entity.py index 176735a44..a782f8cbf 100644 --- a/openedx_learning/apps/authoring/publishing/models/publishable_entity.py +++ b/openedx_learning/apps/authoring/publishing/models/publishable_entity.py @@ -135,6 +135,7 @@ class PublishableEntity(models.Model): ) class Meta: + db_table = 'oel_publishing_publishableentity' constraints = [ # Keys are unique within a given LearningPackage. models.UniqueConstraint( @@ -237,6 +238,7 @@ def __str__(self): return f"{self.entity.key} @ v{self.version_num} - {self.title}" class Meta: + db_table = 'oel_publishing_publishableentityversion' constraints = [ # Prevent the situation where we have multiple # PublishableEntityVersions claiming to be the same version_num for @@ -305,6 +307,7 @@ class PublishableEntityVersionDependency(models.Model): referenced_entity = models.ForeignKey(PublishableEntity, on_delete=models.RESTRICT) class Meta: + db_table = 'oel_publishing_publishableentityversiondependency' constraints = [ models.UniqueConstraint( fields=["referring_version", "referenced_entity"], diff --git a/openedx_learning/apps/authoring/sections/apps.py b/openedx_learning/apps/authoring/sections/apps.py deleted file mode 100644 index f506229e2..000000000 --- a/openedx_learning/apps/authoring/sections/apps.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Sections Django application initialization. -""" - -from django.apps import AppConfig - - -class SectionsConfig(AppConfig): - """ - Configuration for the Sections Django application. - """ - - name = "openedx_learning.apps.authoring.sections" - verbose_name = "Learning Core > Authoring > Sections" - default_auto_field = "django.db.models.BigAutoField" - label = "oel_sections" - - def ready(self): - """ - Register Section and SectionVersion. - """ - from ..publishing.api import register_publishable_models # pylint: disable=import-outside-toplevel - from .models import Section, SectionVersion # pylint: disable=import-outside-toplevel - - register_publishable_models(Section, SectionVersion) diff --git a/openedx_learning/apps/authoring/subsections/apps.py b/openedx_learning/apps/authoring/subsections/apps.py deleted file mode 100644 index 950e14143..000000000 --- a/openedx_learning/apps/authoring/subsections/apps.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Subsection Django application initialization. -""" - -from django.apps import AppConfig - - -class SubsectionsConfig(AppConfig): - """ - Configuration for the subsections Django application. - """ - - name = "openedx_learning.apps.authoring.subsections" - verbose_name = "Learning Core > Authoring > Subsections" - default_auto_field = "django.db.models.BigAutoField" - label = "oel_subsections" - - def ready(self): - """ - Register Subsection and SubsectionVersion. - """ - from ..publishing.api import register_publishable_models # pylint: disable=import-outside-toplevel - from .models import Subsection, SubsectionVersion # pylint: disable=import-outside-toplevel - - register_publishable_models(Subsection, SubsectionVersion) diff --git a/openedx_learning/apps/authoring/units/apps.py b/openedx_learning/apps/authoring/units/apps.py deleted file mode 100644 index 17affcf25..000000000 --- a/openedx_learning/apps/authoring/units/apps.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Unit Django application initialization. -""" - -from django.apps import AppConfig - - -class UnitsConfig(AppConfig): - """ - Configuration for the units Django application. - """ - - name = "openedx_learning.apps.authoring.units" - verbose_name = "Learning Core > Authoring > Units" - default_auto_field = "django.db.models.BigAutoField" - label = "oel_units" - - def ready(self): - """ - Register Unit and UnitVersion. - """ - from ..publishing.api import register_publishable_models # pylint: disable=import-outside-toplevel - from .models import Unit, UnitVersion # pylint: disable=import-outside-toplevel - - register_publishable_models(Unit, UnitVersion) diff --git a/projects/dev.py b/projects/dev.py index 4a05c2f46..082a300d2 100644 --- a/projects/dev.py +++ b/projects/dev.py @@ -31,14 +31,18 @@ "django.contrib.admin", "django.contrib.admindocs", # Learning Core Apps - "openedx_learning.apps.authoring.collections", - "openedx_learning.apps.authoring.components", - "openedx_learning.apps.authoring.contents", - "openedx_learning.apps.authoring.publishing", - "openedx_learning.apps.authoring.sections", - "openedx_learning.apps.authoring.subsections", - "openedx_learning.apps.authoring.units", - "openedx_learning.apps.authoring.backup_restore", + + "openedx_learning.apps.authoring", + + #"openedx_learning.apps.authoring.collections", + #"openedx_learning.apps.authoring.components", + #"openedx_learning.apps.authoring.contents", + #"openedx_learning.apps.authoring.publishing", + #"openedx_learning.apps.authoring.sections", + #"openedx_learning.apps.authoring.subsections", + #"openedx_learning.apps.authoring.units", + #"openedx_learning.apps.authoring.backup_restore", + # Learning Contrib Apps # "openedx_learning.contrib.media_server.apps.MediaServerConfig", # Apps that don't belong in this repo in the long term, but are here to make From 865548f92091290efaaab35b9cfbf3787379c68c Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Mon, 29 Dec 2025 02:56:51 -0500 Subject: [PATCH 03/13] refactor: index naming issues --- .../collections/migrations/0001_initial.py | 33 ---- ...ion_name_collection_created_by_and_more.py | 53 ------ .../migrations/0003_collection_entities.py | 38 ---- .../migrations/0004_collection_key.py | 57 ------ ...ection_options_alter_collection_enabled.py | 18 -- .../apps/authoring/collections/models.py | 7 +- .../components/migrations/0001_initial.py | 97 ---------- .../0002_alter_componentversioncontent_key.py | 20 --- ...nentversioncontent_learner_downloadable.py | 17 -- ...004_remove_componentversioncontent_uuid.py | 17 -- .../components/migrations/__init__.py | 0 .../apps/authoring/components/models.py | 7 +- .../contents/migrations/0001_initial.py | 66 ------- .../authoring/contents/migrations/__init__.py | 0 .../0002_rename_tables_to_oel_authoring.py | 106 +++++++++++ .../migrations => modules}/__init__.py | 0 .../publishing/migrations/0001_initial.py | 166 ------------------ ...0002_alter_learningpackage_key_and_more.py | 25 --- .../publishing/migrations/0003_containers.py | 54 ------ .../0004_publishableentity_can_stand_alone.py | 21 --- .../0005_alter_entitylistrow_options.py | 17 -- .../migrations/0006_draftchangelog.py | 68 ------- .../0007_bootstrap_draftchangelog.py | 94 ---------- ...r_draftchangelogrecord_options_and_more.py | 31 ---- .../0009_dependencies_and_hashing.py | 62 ------- .../migrations/0010_backfill_dependencies.py | 149 ---------------- .../publishing/migrations/__init__.py | 0 .../authoring/publishing/models/container.py | 5 - .../authoring/publishing/models/draft_log.py | 6 - .../publishing/models/entity_list.py | 4 - .../publishing/models/learning_package.py | 1 - .../publishing/models/publish_log.py | 4 - .../publishing/models/publishable_entity.py | 3 - .../sections/migrations/0001_initial.py | 36 ---- .../authoring/sections/migrations/__init__.py | 0 .../subsections/migrations/0001_initial.py | 36 ---- .../subsections/migrations/__init__.py | 0 .../units/migrations/0001_initial.py | 36 ---- .../authoring/units/migrations/__init__.py | 0 test_settings.py | 20 +-- 40 files changed, 114 insertions(+), 1260 deletions(-) delete mode 100644 openedx_learning/apps/authoring/collections/migrations/0001_initial.py delete mode 100644 openedx_learning/apps/authoring/collections/migrations/0002_remove_collection_name_collection_created_by_and_more.py delete mode 100644 openedx_learning/apps/authoring/collections/migrations/0003_collection_entities.py delete mode 100644 openedx_learning/apps/authoring/collections/migrations/0004_collection_key.py delete mode 100644 openedx_learning/apps/authoring/collections/migrations/0005_alter_collection_options_alter_collection_enabled.py delete mode 100644 openedx_learning/apps/authoring/components/migrations/0001_initial.py delete mode 100644 openedx_learning/apps/authoring/components/migrations/0002_alter_componentversioncontent_key.py delete mode 100644 openedx_learning/apps/authoring/components/migrations/0003_remove_componentversioncontent_learner_downloadable.py delete mode 100644 openedx_learning/apps/authoring/components/migrations/0004_remove_componentversioncontent_uuid.py delete mode 100644 openedx_learning/apps/authoring/components/migrations/__init__.py delete mode 100644 openedx_learning/apps/authoring/contents/migrations/0001_initial.py delete mode 100644 openedx_learning/apps/authoring/contents/migrations/__init__.py create mode 100644 openedx_learning/apps/authoring/migrations/0002_rename_tables_to_oel_authoring.py rename openedx_learning/apps/authoring/{collections/migrations => modules}/__init__.py (100%) delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/0001_initial.py delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/0002_alter_learningpackage_key_and_more.py delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/0003_containers.py delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/0004_publishableentity_can_stand_alone.py delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/0005_alter_entitylistrow_options.py delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/0006_draftchangelog.py delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/0007_bootstrap_draftchangelog.py delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/0008_alter_draftchangelogrecord_options_and_more.py delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/0009_dependencies_and_hashing.py delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/0010_backfill_dependencies.py delete mode 100644 openedx_learning/apps/authoring/publishing/migrations/__init__.py delete mode 100644 openedx_learning/apps/authoring/sections/migrations/0001_initial.py delete mode 100644 openedx_learning/apps/authoring/sections/migrations/__init__.py delete mode 100644 openedx_learning/apps/authoring/subsections/migrations/0001_initial.py delete mode 100644 openedx_learning/apps/authoring/subsections/migrations/__init__.py delete mode 100644 openedx_learning/apps/authoring/units/migrations/0001_initial.py delete mode 100644 openedx_learning/apps/authoring/units/migrations/__init__.py diff --git a/openedx_learning/apps/authoring/collections/migrations/0001_initial.py b/openedx_learning/apps/authoring/collections/migrations/0001_initial.py deleted file mode 100644 index 0fdee2734..000000000 --- a/openedx_learning/apps/authoring/collections/migrations/0001_initial.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 4.2.14 on 2024-08-05 20:42 - -import django.db.models.deletion -from django.db import migrations, models - -import openedx_learning.lib.fields - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('oel_publishing', '0002_alter_learningpackage_key_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='Collection', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('name', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, db_index=True, help_text='The name of the collection.', max_length=255)), - ('description', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, help_text='Provides extra information for the user about this collection.', max_length=10000)), - ('enabled', models.BooleanField(default=True, help_text='Whether the collection is enabled or not.')), - ('created', models.DateTimeField(auto_now_add=True)), - ('modified', models.DateTimeField(auto_now=True)), - ('learning_package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.learningpackage')), - ], - options={ - 'verbose_name_plural': 'Collections', - }, - ), - ] diff --git a/openedx_learning/apps/authoring/collections/migrations/0002_remove_collection_name_collection_created_by_and_more.py b/openedx_learning/apps/authoring/collections/migrations/0002_remove_collection_name_collection_created_by_and_more.py deleted file mode 100644 index eee95e509..000000000 --- a/openedx_learning/apps/authoring/collections/migrations/0002_remove_collection_name_collection_created_by_and_more.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 4.2.14 on 2024-08-14 14:20 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - -import openedx_learning.lib.fields -import openedx_learning.lib.validators - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('oel_collections', '0001_initial'), - ] - - operations = [ - migrations.RemoveField( - model_name='collection', - name='name', - ), - migrations.AddField( - model_name='collection', - name='created_by', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), - ), - migrations.AddField( - model_name='collection', - name='title', - field=openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, default='Collection', help_text='The title of the collection.', max_length=500), - preserve_default=False, - ), - migrations.AlterField( - model_name='collection', - name='created', - field=models.DateTimeField(auto_now_add=True, validators=[openedx_learning.lib.validators.validate_utc_datetime]), - ), - migrations.AlterField( - model_name='collection', - name='description', - field=openedx_learning.lib.fields.MultiCollationTextField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, default='', help_text='Provides extra information for the user about this collection.', max_length=10000), - ), - migrations.AlterField( - model_name='collection', - name='modified', - field=models.DateTimeField(auto_now=True, validators=[openedx_learning.lib.validators.validate_utc_datetime]), - ), - migrations.AddIndex( - model_name='collection', - index=models.Index(fields=['learning_package', 'title'], name='oel_collect_learnin_dfaf89_idx'), - ), - ] diff --git a/openedx_learning/apps/authoring/collections/migrations/0003_collection_entities.py b/openedx_learning/apps/authoring/collections/migrations/0003_collection_entities.py deleted file mode 100644 index 1c5e84055..000000000 --- a/openedx_learning/apps/authoring/collections/migrations/0003_collection_entities.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 4.2.15 on 2024-08-29 00:05 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - -import openedx_learning.lib.validators - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('oel_publishing', '0002_alter_learningpackage_key_and_more'), - ('oel_collections', '0002_remove_collection_name_collection_created_by_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='CollectionPublishableEntity', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', models.DateTimeField(auto_now_add=True, validators=[openedx_learning.lib.validators.validate_utc_datetime])), - ('collection', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_collections.collection')), - ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), - ('entity', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.publishableentity')), - ], - ), - migrations.AddField( - model_name='collection', - name='entities', - field=models.ManyToManyField(related_name='collections', through='oel_collections.CollectionPublishableEntity', to='oel_publishing.publishableentity'), - ), - migrations.AddConstraint( - model_name='collectionpublishableentity', - constraint=models.UniqueConstraint(fields=('collection', 'entity'), name='oel_collections_cpe_uniq_col_ent'), - ), - ] diff --git a/openedx_learning/apps/authoring/collections/migrations/0004_collection_key.py b/openedx_learning/apps/authoring/collections/migrations/0004_collection_key.py deleted file mode 100644 index 843419eec..000000000 --- a/openedx_learning/apps/authoring/collections/migrations/0004_collection_key.py +++ /dev/null @@ -1,57 +0,0 @@ -# Generated by Django 4.2.15 on 2024-09-04 23:15 - -from django.db import migrations, models -from django.utils.crypto import get_random_string - -import openedx_learning.lib.fields - - -def generate_keys(apps, schema_editor): - """ - Generates a random strings to initialize the key field where NULL. - """ - length = 50 - Collection = apps.get_model("oel_collections", "Collection") - for collection in Collection.objects.filter(key=None): - # Keep generating keys until we get a unique one - key = get_random_string(length) - while Collection.objects.filter(key=key).exists(): - key = get_random_string(length) - - collection.key = key - collection.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_collections', '0003_collection_entities'), - ] - - operations = [ - # 1. Temporarily add this field with null=True, blank=True - migrations.AddField( - model_name='collection', - name='key', - field=openedx_learning.lib.fields.MultiCollationCharField( - db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, - db_column='_key', max_length=500, null=True, blank=True), - preserve_default=False, - ), - # 2. Populate the null keys - migrations.RunPython(generate_keys), - # 3. Add null=False, blank=False to disallow NULL values - migrations.AlterField( - model_name='collection', - name='key', - field=openedx_learning.lib.fields.MultiCollationCharField( - db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, - db_column='_key', max_length=500, null=False, blank=False), - preserve_default=False, - ), - # 4. Enforce unique constraint - migrations.AddConstraint( - model_name='collection', - constraint=models.UniqueConstraint(fields=('learning_package', 'key'), name='oel_coll_uniq_lp_key'), - ), - ] diff --git a/openedx_learning/apps/authoring/collections/migrations/0005_alter_collection_options_alter_collection_enabled.py b/openedx_learning/apps/authoring/collections/migrations/0005_alter_collection_options_alter_collection_enabled.py deleted file mode 100644 index 17405dac6..000000000 --- a/openedx_learning/apps/authoring/collections/migrations/0005_alter_collection_options_alter_collection_enabled.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.15 on 2024-09-24 07:31 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_collections', '0004_collection_key'), - ] - - operations = [ - migrations.AlterField( - model_name='collection', - name='enabled', - field=models.BooleanField(default=True, help_text='Disabled collections are "soft deleted", and should be re-enabled before use, or be deleted.'), - ), - ] diff --git a/openedx_learning/apps/authoring/collections/models.py b/openedx_learning/apps/authoring/collections/models.py index 48a0bb072..225f2fc20 100644 --- a/openedx_learning/apps/authoring/collections/models.py +++ b/openedx_learning/apps/authoring/collections/models.py @@ -168,7 +168,6 @@ class Collection(models.Model): ) class Meta: - db_table = 'oel_collections_collection' verbose_name_plural = "Collections" constraints = [ # Keys are unique within a given LearningPackage. @@ -181,7 +180,10 @@ class Meta: ), ] indexes = [ - models.Index(fields=["learning_package", "title"]), + models.Index( + fields=["learning_package", "title"], + name="oel_authoring_coll_lp_title", + ), ] def __repr__(self) -> str: @@ -223,7 +225,6 @@ class CollectionPublishableEntity(models.Model): ) class Meta: - db_table = 'oel_collections_collectionpublishableentity' constraints = [ # Prevent race conditions from making multiple rows associating the # same Collection to the same Entity. diff --git a/openedx_learning/apps/authoring/components/migrations/0001_initial.py b/openedx_learning/apps/authoring/components/migrations/0001_initial.py deleted file mode 100644 index ece93796e..000000000 --- a/openedx_learning/apps/authoring/components/migrations/0001_initial.py +++ /dev/null @@ -1,97 +0,0 @@ -# Generated by Django 3.2.23 on 2024-02-06 03:23 - -import uuid - -import django.db.models.deletion -from django.db import migrations, models - -import openedx_learning.lib.fields - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('oel_contents', '0001_initial'), - ('oel_publishing', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Component', - fields=[ - ('publishable_entity', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_publishing.publishableentity')), - ('local_key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, max_length=500)), - ], - options={ - 'verbose_name': 'Component', - 'verbose_name_plural': 'Components', - }, - ), - migrations.CreateModel( - name='ComponentType', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('namespace', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, max_length=100)), - ('name', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, max_length=100)), - ], - ), - migrations.CreateModel( - name='ComponentVersion', - fields=[ - ('publishable_entity_version', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_publishing.publishableentityversion')), - ('component', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='versions', to='oel_components.component')), - ], - options={ - 'verbose_name': 'Component Version', - 'verbose_name_plural': 'Component Versions', - }, - ), - migrations.CreateModel( - name='ComponentVersionContent', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), - ('key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, max_length=500)), - ('learner_downloadable', models.BooleanField(default=False)), - ('component_version', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_components.componentversion')), - ('content', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_contents.content')), - ], - ), - migrations.AddField( - model_name='componentversion', - name='contents', - field=models.ManyToManyField(related_name='component_versions', through='oel_components.ComponentVersionContent', to='oel_contents.Content'), - ), - migrations.AddField( - model_name='component', - name='component_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='oel_components.componenttype'), - ), - migrations.AddField( - model_name='component', - name='learning_package', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.learningpackage'), - ), - migrations.AddIndex( - model_name='componentversioncontent', - index=models.Index(fields=['content', 'component_version'], name='oel_cvcontent_c_cv'), - ), - migrations.AddIndex( - model_name='componentversioncontent', - index=models.Index(fields=['component_version', 'content'], name='oel_cvcontent_cv_d'), - ), - migrations.AddConstraint( - model_name='componentversioncontent', - constraint=models.UniqueConstraint(fields=('component_version', 'key'), name='oel_cvcontent_uniq_cv_key'), - ), - migrations.AddIndex( - model_name='component', - index=models.Index(fields=['component_type', 'local_key'], name='oel_component_idx_ct_lk'), - ), - migrations.AddConstraint( - model_name='component', - constraint=models.UniqueConstraint(fields=('learning_package', 'component_type', 'local_key'), name='oel_component_uniq_lc_ct_lk'), - ), - ] diff --git a/openedx_learning/apps/authoring/components/migrations/0002_alter_componentversioncontent_key.py b/openedx_learning/apps/authoring/components/migrations/0002_alter_componentversioncontent_key.py deleted file mode 100644 index ee12970d2..000000000 --- a/openedx_learning/apps/authoring/components/migrations/0002_alter_componentversioncontent_key.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.2.10 on 2024-02-14 22:02 - -from django.db import migrations - -import openedx_learning.lib.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_components', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='componentversioncontent', - name='key', - field=openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, db_column='_key', max_length=500), - ), - ] diff --git a/openedx_learning/apps/authoring/components/migrations/0003_remove_componentversioncontent_learner_downloadable.py b/openedx_learning/apps/authoring/components/migrations/0003_remove_componentversioncontent_learner_downloadable.py deleted file mode 100644 index 4ae618b77..000000000 --- a/openedx_learning/apps/authoring/components/migrations/0003_remove_componentversioncontent_learner_downloadable.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 4.2.16 on 2024-11-06 17:14 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_components', '0002_alter_componentversioncontent_key'), - ] - - operations = [ - migrations.RemoveField( - model_name='componentversioncontent', - name='learner_downloadable', - ), - ] diff --git a/openedx_learning/apps/authoring/components/migrations/0004_remove_componentversioncontent_uuid.py b/openedx_learning/apps/authoring/components/migrations/0004_remove_componentversioncontent_uuid.py deleted file mode 100644 index 5005aa4ec..000000000 --- a/openedx_learning/apps/authoring/components/migrations/0004_remove_componentversioncontent_uuid.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 4.2.23 on 2025-10-02 14:00 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_components', '0003_remove_componentversioncontent_learner_downloadable'), - ] - - operations = [ - migrations.RemoveField( - model_name='componentversioncontent', - name='uuid', - ), - ] diff --git a/openedx_learning/apps/authoring/components/migrations/__init__.py b/openedx_learning/apps/authoring/components/migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openedx_learning/apps/authoring/components/models.py b/openedx_learning/apps/authoring/components/models.py index d84e42bba..966a9d2fb 100644 --- a/openedx_learning/apps/authoring/components/models.py +++ b/openedx_learning/apps/authoring/components/models.py @@ -63,6 +63,7 @@ class ComponentType(models.Model): # the UsageKey. name = case_sensitive_char_field(max_length=100, blank=True) + # TODO: this needs to go into a class Meta constraints = [ models.UniqueConstraint( fields=[ @@ -76,9 +77,6 @@ class ComponentType(models.Model): def __str__(self) -> str: return f"{self.namespace}:{self.name}" - class Meta: - db_table = 'oel_components_componenttype' - class Component(PublishableEntityMixin): """ @@ -158,7 +156,6 @@ class Component(PublishableEntityMixin): local_key = key_field() class Meta: - db_table = 'oel_components_component' constraints = [ # The combination of (component_type, local_key) is unique within # a given LearningPackage. Note that this means it is possible to @@ -221,7 +218,6 @@ class ComponentVersion(PublishableEntityVersionMixin): ) class Meta: - db_table = 'oel_components_componentversion' verbose_name = "Component Version" verbose_name_plural = "Component Versions" @@ -253,7 +249,6 @@ class ComponentVersionContent(models.Model): key = key_field(db_column="_key") class Meta: - db_table = 'oel_components_componentversioncontent' constraints = [ # Uniqueness is only by ComponentVersion and key. If for some reason # a ComponentVersion wants to associate the same piece of content diff --git a/openedx_learning/apps/authoring/contents/migrations/0001_initial.py b/openedx_learning/apps/authoring/contents/migrations/0001_initial.py deleted file mode 100644 index 1abf65adf..000000000 --- a/openedx_learning/apps/authoring/contents/migrations/0001_initial.py +++ /dev/null @@ -1,66 +0,0 @@ -# Generated by Django 3.2.23 on 2024-02-06 03:23 - -import django.core.validators -import django.db.models.deletion -from django.db import migrations, models - -import openedx_learning.lib.fields -import openedx_learning.lib.validators - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('oel_publishing', '0001_initial'), - ] - - operations = [ - migrations.CreateModel( - name='Content', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('size', models.PositiveBigIntegerField(validators=[django.core.validators.MaxValueValidator(50000000)])), - ('hash_digest', models.CharField(editable=False, max_length=40)), - ('has_file', models.BooleanField()), - ('text', openedx_learning.lib.fields.MultiCollationTextField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=50000, null=True)), - ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), - ], - options={ - 'verbose_name': 'Content', - 'verbose_name_plural': 'Contents', - }, - ), - migrations.CreateModel( - name='MediaType', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('type', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=127)), - ('sub_type', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=127)), - ('suffix', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=127)), - ], - ), - migrations.AddConstraint( - model_name='mediatype', - constraint=models.UniqueConstraint(fields=('type', 'sub_type', 'suffix'), name='oel_contents_uniq_t_st_sfx'), - ), - migrations.AddField( - model_name='content', - name='learning_package', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.learningpackage'), - ), - migrations.AddField( - model_name='content', - name='media_type', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='oel_contents.mediatype'), - ), - migrations.AddIndex( - model_name='content', - index=models.Index(fields=['learning_package', '-size'], name='oel_content_idx_lp_rsize'), - ), - migrations.AddConstraint( - model_name='content', - constraint=models.UniqueConstraint(fields=('learning_package', 'media_type', 'hash_digest'), name='oel_content_uniq_lc_media_type_hash_digest'), - ), - ] diff --git a/openedx_learning/apps/authoring/contents/migrations/__init__.py b/openedx_learning/apps/authoring/contents/migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openedx_learning/apps/authoring/migrations/0002_rename_tables_to_oel_authoring.py b/openedx_learning/apps/authoring/migrations/0002_rename_tables_to_oel_authoring.py new file mode 100644 index 000000000..41fdc31b9 --- /dev/null +++ b/openedx_learning/apps/authoring/migrations/0002_rename_tables_to_oel_authoring.py @@ -0,0 +1,106 @@ +# Generated by Django 5.2.9 on 2025-12-29 07:07 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('oel_authoring', '0001_initial'), + ] + + operations = [ + migrations.RenameIndex( + model_name='collection', + new_name='oel_authoring_coll_lp_title', + old_name='oel_collect_learnin_dfaf89_idx', + ), + migrations.AlterModelTable( + name='collection', + table=None, + ), + migrations.AlterModelTable( + name='collectionpublishableentity', + table=None, + ), + migrations.AlterModelTable( + name='component', + table=None, + ), + migrations.AlterModelTable( + name='componenttype', + table=None, + ), + migrations.AlterModelTable( + name='componentversion', + table=None, + ), + migrations.AlterModelTable( + name='componentversioncontent', + table=None, + ), + migrations.AlterModelTable( + name='container', + table=None, + ), + migrations.AlterModelTable( + name='containerversion', + table=None, + ), + migrations.AlterModelTable( + name='draft', + table=None, + ), + migrations.AlterModelTable( + name='draftchangelog', + table=None, + ), + migrations.AlterModelTable( + name='draftchangelogrecord', + table=None, + ), + migrations.AlterModelTable( + name='draftsideeffect', + table=None, + ), + migrations.AlterModelTable( + name='entitylist', + table=None, + ), + migrations.AlterModelTable( + name='entitylistrow', + table=None, + ), + migrations.AlterModelTable( + name='learningpackage', + table=None, + ), + migrations.AlterModelTable( + name='publishableentity', + table=None, + ), + migrations.AlterModelTable( + name='publishableentityversion', + table=None, + ), + migrations.AlterModelTable( + name='publishableentityversiondependency', + table=None, + ), + migrations.AlterModelTable( + name='published', + table=None, + ), + migrations.AlterModelTable( + name='publishlog', + table=None, + ), + migrations.AlterModelTable( + name='publishlogrecord', + table=None, + ), + migrations.AlterModelTable( + name='publishsideeffect', + table=None, + ), + ] diff --git a/openedx_learning/apps/authoring/collections/migrations/__init__.py b/openedx_learning/apps/authoring/modules/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/collections/migrations/__init__.py rename to openedx_learning/apps/authoring/modules/__init__.py diff --git a/openedx_learning/apps/authoring/publishing/migrations/0001_initial.py b/openedx_learning/apps/authoring/publishing/migrations/0001_initial.py deleted file mode 100644 index 6ffb8b857..000000000 --- a/openedx_learning/apps/authoring/publishing/migrations/0001_initial.py +++ /dev/null @@ -1,166 +0,0 @@ -# Generated by Django 3.2.23 on 2024-02-06 00:36 - -import uuid - -import django.core.validators -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - -import openedx_learning.lib.fields -import openedx_learning.lib.validators - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='LearningPackage', - fields=[ - ('id', models.AutoField(primary_key=True, serialize=False)), - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), - ('key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, max_length=500)), - ('title', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=500)), - ('description', openedx_learning.lib.fields.MultiCollationTextField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, default='', max_length=10000)), - ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), - ('updated', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), - ], - options={ - 'verbose_name': 'Learning Package', - 'verbose_name_plural': 'Learning Packages', - }, - ), - migrations.CreateModel( - name='PublishableEntity', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), - ('key', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, max_length=500)), - ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), - ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), - ('learning_package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publishable_entities', to='oel_publishing.learningpackage')), - ], - options={ - 'verbose_name': 'Publishable Entity', - 'verbose_name_plural': 'Publishable Entities', - }, - ), - migrations.CreateModel( - name='PublishableEntityVersion', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), - ('title', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, default='', max_length=500)), - ('version_num', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1)])), - ('created', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), - ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), - ('entity', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='versions', to='oel_publishing.publishableentity')), - ], - options={ - 'verbose_name': 'Publishable Entity Version', - 'verbose_name_plural': 'Publishable Entity Versions', - }, - ), - migrations.CreateModel( - name='PublishLog', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), - ('message', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, default='', max_length=500)), - ('published_at', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), - ('learning_package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.learningpackage')), - ('published_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'Publish Log', - 'verbose_name_plural': 'Publish Logs', - }, - ), - migrations.CreateModel( - name='Draft', - fields=[ - ('entity', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_publishing.publishableentity')), - ], - ), - migrations.CreateModel( - name='Published', - fields=[ - ('entity', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_publishing.publishableentity')), - ], - options={ - 'verbose_name': 'Published Entity', - 'verbose_name_plural': 'Published Entities', - }, - ), - migrations.CreateModel( - name='PublishLogRecord', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('entity', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.publishableentity')), - ('new_version', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.publishableentityversion')), - ('old_version', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, related_name='+', to='oel_publishing.publishableentityversion')), - ('publish_log', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='records', to='oel_publishing.publishlog')), - ], - options={ - 'verbose_name': 'Publish Log Record', - 'verbose_name_plural': 'Publish Log Records', - }, - ), - migrations.AddConstraint( - model_name='learningpackage', - constraint=models.UniqueConstraint(fields=('key',), name='oel_publishing_lp_uniq_key'), - ), - migrations.AddIndex( - model_name='publishlogrecord', - index=models.Index(fields=['entity', '-publish_log'], name='oel_plr_idx_entity_rplr'), - ), - migrations.AddConstraint( - model_name='publishlogrecord', - constraint=models.UniqueConstraint(fields=('publish_log', 'entity'), name='oel_plr_uniq_pl_publishable'), - ), - migrations.AddField( - model_name='published', - name='publish_log_record', - field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.publishlogrecord'), - ), - migrations.AddField( - model_name='published', - name='version', - field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.publishableentityversion'), - ), - migrations.AddIndex( - model_name='publishableentityversion', - index=models.Index(fields=['entity', '-created'], name='oel_pv_idx_entity_rcreated'), - ), - migrations.AddIndex( - model_name='publishableentityversion', - index=models.Index(fields=['title'], name='oel_pv_idx_title'), - ), - migrations.AddConstraint( - model_name='publishableentityversion', - constraint=models.UniqueConstraint(fields=('entity', 'version_num'), name='oel_pv_uniq_entity_version_num'), - ), - migrations.AddIndex( - model_name='publishableentity', - index=models.Index(fields=['key'], name='oel_pub_ent_idx_key'), - ), - migrations.AddIndex( - model_name='publishableentity', - index=models.Index(fields=['learning_package', '-created'], name='oel_pub_ent_idx_lp_rcreated'), - ), - migrations.AddConstraint( - model_name='publishableentity', - constraint=models.UniqueConstraint(fields=('learning_package', 'key'), name='oel_pub_ent_uniq_lp_key'), - ), - migrations.AddField( - model_name='draft', - name='version', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.publishableentityversion'), - ), - ] diff --git a/openedx_learning/apps/authoring/publishing/migrations/0002_alter_learningpackage_key_and_more.py b/openedx_learning/apps/authoring/publishing/migrations/0002_alter_learningpackage_key_and_more.py deleted file mode 100644 index 0a4c3b48f..000000000 --- a/openedx_learning/apps/authoring/publishing/migrations/0002_alter_learningpackage_key_and_more.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 4.2.10 on 2024-02-14 22:02 - -from django.db import migrations - -import openedx_learning.lib.fields - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_publishing', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='learningpackage', - name='key', - field=openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, db_column='_key', max_length=500), - ), - migrations.AlterField( - model_name='publishableentity', - name='key', - field=openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_bin', 'sqlite': 'BINARY'}, db_column='_key', max_length=500), - ), - ] diff --git a/openedx_learning/apps/authoring/publishing/migrations/0003_containers.py b/openedx_learning/apps/authoring/publishing/migrations/0003_containers.py deleted file mode 100644 index 55e967771..000000000 --- a/openedx_learning/apps/authoring/publishing/migrations/0003_containers.py +++ /dev/null @@ -1,54 +0,0 @@ -# Generated by Django 4.2.19 on 2025-03-11 04:10 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_publishing', '0002_alter_learningpackage_key_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='Container', - fields=[ - ('publishable_entity', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_publishing.publishableentity')), - ], - options={ - 'abstract': False, - }, - ), - migrations.CreateModel( - name='EntityList', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ], - ), - migrations.CreateModel( - name='EntityListRow', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('order_num', models.PositiveIntegerField()), - ('entity', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.publishableentity')), - ('entity_list', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.entitylist')), - ('entity_version', models.ForeignKey(null=True, on_delete=django.db.models.deletion.RESTRICT, related_name='+', to='oel_publishing.publishableentityversion')), - ], - ), - migrations.CreateModel( - name='ContainerVersion', - fields=[ - ('publishable_entity_version', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='oel_publishing.publishableentityversion')), - ('container', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='versions', to='oel_publishing.container')), - ('entity_list', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='container_versions', to='oel_publishing.entitylist')), - ], - options={ - 'abstract': False, - }, - ), - migrations.AddConstraint( - model_name='entitylistrow', - constraint=models.UniqueConstraint(fields=('entity_list', 'order_num'), name='oel_publishing_elist_row_order'), - ), - ] diff --git a/openedx_learning/apps/authoring/publishing/migrations/0004_publishableentity_can_stand_alone.py b/openedx_learning/apps/authoring/publishing/migrations/0004_publishableentity_can_stand_alone.py deleted file mode 100644 index 9949d159b..000000000 --- a/openedx_learning/apps/authoring/publishing/migrations/0004_publishableentity_can_stand_alone.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.2.19 on 2025-03-17 11:07 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_publishing', '0003_containers'), - ] - - operations = [ - migrations.AddField( - model_name='publishableentity', - name='can_stand_alone', - field=models.BooleanField( - default=True, - help_text="Set to True when created independently, False when created as part of a container.", - ), - ), - ] diff --git a/openedx_learning/apps/authoring/publishing/migrations/0005_alter_entitylistrow_options.py b/openedx_learning/apps/authoring/publishing/migrations/0005_alter_entitylistrow_options.py deleted file mode 100644 index 84d603d51..000000000 --- a/openedx_learning/apps/authoring/publishing/migrations/0005_alter_entitylistrow_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 5.2 on 2025-04-08 10:50 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_publishing', '0004_publishableentity_can_stand_alone'), - ] - - operations = [ - migrations.AlterModelOptions( - name='entitylistrow', - options={'ordering': ['order_num']}, - ), - ] diff --git a/openedx_learning/apps/authoring/publishing/migrations/0006_draftchangelog.py b/openedx_learning/apps/authoring/publishing/migrations/0006_draftchangelog.py deleted file mode 100644 index b72e16843..000000000 --- a/openedx_learning/apps/authoring/publishing/migrations/0006_draftchangelog.py +++ /dev/null @@ -1,68 +0,0 @@ -# Generated by Django 4.2.18 on 2025-03-28 02:21 - -import uuid - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - -import openedx_learning.lib.validators - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('oel_publishing', '0005_alter_entitylistrow_options'), - ] - - operations = [ - migrations.CreateModel( - name='DraftChangeLog', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='UUID')), - ('changed_at', models.DateTimeField(validators=[openedx_learning.lib.validators.validate_utc_datetime])), - ('changed_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), - ('learning_package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.learningpackage')), - ], - options={ - 'verbose_name': 'Draft Change Log', - 'verbose_name_plural': 'Draft Change Logs', - }, - ), - migrations.CreateModel( - name='DraftChangeLogRecord', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('draft_change_log', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='changes', to='oel_publishing.draftchangelog')), - ('entity', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.publishableentity')), - ('new_version', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.publishableentityversion')), - ('old_version', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.RESTRICT, related_name='+', to='oel_publishing.publishableentityversion')), - ], - options={ - 'verbose_name': 'Draft Log', - 'verbose_name_plural': 'Draft Log', - }, - ), - migrations.CreateModel( - name='DraftSideEffect', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('cause', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='causes', to='oel_publishing.draftchangelogrecord')), - ('effect', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='caused_by', to='oel_publishing.draftchangelogrecord')), - ], - ), - migrations.AddConstraint( - model_name='draftsideeffect', - constraint=models.UniqueConstraint(fields=('cause', 'effect'), name='oel_pub_dse_uniq_c_e'), - ), - migrations.AddIndex( - model_name='draftchangelogrecord', - index=models.Index(fields=['entity', '-draft_change_log'], name='oel_dlr_idx_entity_rdcl'), - ), - migrations.AddConstraint( - model_name='draftchangelogrecord', - constraint=models.UniqueConstraint(fields=('draft_change_log', 'entity'), name='oel_dlr_uniq_dcl'), - ), - ] diff --git a/openedx_learning/apps/authoring/publishing/migrations/0007_bootstrap_draftchangelog.py b/openedx_learning/apps/authoring/publishing/migrations/0007_bootstrap_draftchangelog.py deleted file mode 100644 index 5c8ab3735..000000000 --- a/openedx_learning/apps/authoring/publishing/migrations/0007_bootstrap_draftchangelog.py +++ /dev/null @@ -1,94 +0,0 @@ -""" -Bootstrap DraftChangeLogs - -DraftChangeLog and DraftChangeLogRecord are being introduced after Drafts, so -we're going to retroactively make entries for all the changes that were in our -Learning Packages. - -This migration will try to reconstruct create, edit, reset-to-published, and -delete operations, but it won't be fully accurate because we only have the -create dates of the versions and the current state of active Drafts to go on. -This means we won't accurately capture when things were deleted and then reset, -or when reset and then later edited. We're also missing the user for a number of -these operations, so we'll add those with null created_by entries. Addressing -these gaps is a big part of why we created DraftChangeLogs in the first place. -""" -# Generated by Django 4.2.18 on 2025-03-13 10:29 -import logging -from datetime import datetime, timezone - -from django.db import migrations - -logger = logging.getLogger(__name__) - - -def bootstrap_draft_change_logs(apps, schema_editor): - """ - Create a fake DraftChangeSet that encompasses the state of current Drafts. - """ - LearningPackage = apps.get_model("oel_publishing", "LearningPackage") - PublishableEntityVersion = apps.get_model("oel_publishing", "PublishableEntityVersion") - - Draft = apps.get_model("oel_publishing", "Draft") - DraftChangeLogRecord = apps.get_model("oel_publishing", "DraftChangeLogRecord") - DraftChangeLog = apps.get_model("oel_publishing", "DraftChangeLog") - now = datetime.now(tz=timezone.utc) - - for learning_package in LearningPackage.objects.all().order_by("key"): - logger.info(f"Creating bootstrap DraftChangeLogs for {learning_package.key}") - pub_ent_versions = PublishableEntityVersion.objects.filter( - entity__learning_package=learning_package - ).select_related("entity") - - # First cycle though all the simple create/edit operations... - last_version_seen = {} # PublishableEntity.id -> PublishableEntityVersion.id - for pub_ent_version in pub_ent_versions.order_by("pk"): - draft_change_log = DraftChangeLog.objects.create( - learning_package=learning_package, - changed_at=pub_ent_version.created, - changed_by=pub_ent_version.created_by, - ) - DraftChangeLogRecord.objects.create( - draft_change_log=draft_change_log, - entity=pub_ent_version.entity, - old_version_id=last_version_seen.get(pub_ent_version.entity.id), - new_version_id=pub_ent_version.id, - ) - last_version_seen[pub_ent_version.entity.id] = pub_ent_version.id - - # Now that we've created change sets for create/edit operations, we look - # at the latest state of the Draft model in order to determine whether - # we need to apply deletes or resets. - for draft in Draft.objects.filter(entity__learning_package=learning_package).order_by("entity_id"): - last_version_id = last_version_seen.get(draft.entity_id) - if draft.version_id == last_version_id: - continue - # We don't really know who did this or when, so we use None and now. - draft_change_log = DraftChangeLog.objects.create( - learning_package=learning_package, - changed_at=now, - changed_by=None, - ) - DraftChangeLogRecord.objects.create( - draft_change_log=draft_change_log, - entity_id=draft.entity_id, - old_version_id=last_version_id, - new_version_id=draft.version_id, - ) - - -def delete_draft_change_logs(apps, schema_editor): - logger.info(f"Deleting all DraftChangeLogs (reverse migration)") - DraftChangeLog = apps.get_model("oel_publishing", "DraftChangeLog") - DraftChangeLog.objects.all().delete() - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_publishing', '0006_draftchangelog'), - ] - - operations = [ - migrations.RunPython(bootstrap_draft_change_logs, reverse_code=delete_draft_change_logs) - ] diff --git a/openedx_learning/apps/authoring/publishing/migrations/0008_alter_draftchangelogrecord_options_and_more.py b/openedx_learning/apps/authoring/publishing/migrations/0008_alter_draftchangelogrecord_options_and_more.py deleted file mode 100644 index e83bf7202..000000000 --- a/openedx_learning/apps/authoring/publishing/migrations/0008_alter_draftchangelogrecord_options_and_more.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 4.2.20 on 2025-04-17 18:22 -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_publishing', '0007_bootstrap_draftchangelog'), - ] - - operations = [ - migrations.AlterModelOptions( - name='draftchangelogrecord', - options={'verbose_name': 'Draft Change Log Record', 'verbose_name_plural': 'Draft Change Log Records'}, - ), - migrations.AlterModelOptions( - name='draftsideeffect', - options={'verbose_name': 'Draft Side Effect', 'verbose_name_plural': 'Draft Side Effects'}, - ), - migrations.AlterField( - model_name='draftchangelogrecord', - name='draft_change_log', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='records', to='oel_publishing.draftchangelog'), - ), - migrations.AlterField( - model_name='draftsideeffect', - name='effect', - field=models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='affected_by', to='oel_publishing.draftchangelogrecord'), - ), - ] diff --git a/openedx_learning/apps/authoring/publishing/migrations/0009_dependencies_and_hashing.py b/openedx_learning/apps/authoring/publishing/migrations/0009_dependencies_and_hashing.py deleted file mode 100644 index bbed19bd5..000000000 --- a/openedx_learning/apps/authoring/publishing/migrations/0009_dependencies_and_hashing.py +++ /dev/null @@ -1,62 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-29 17:59 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_publishing', '0008_alter_draftchangelogrecord_options_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='draft', - name='draft_log_record', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='oel_publishing.draftchangelogrecord'), - ), - migrations.AddField( - model_name='draftchangelogrecord', - name='dependencies_hash_digest', - field=models.CharField(blank=True, default='', editable=False, max_length=8), - ), - migrations.AddField( - model_name='publishlogrecord', - name='dependencies_hash_digest', - field=models.CharField(blank=True, default='', editable=False, max_length=8), - ), - migrations.CreateModel( - name='PublishableEntityVersionDependency', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('referenced_entity', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, to='oel_publishing.publishableentity')), - ('referring_version', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='oel_publishing.publishableentityversion')), - ], - ), - migrations.AddField( - model_name='publishableentityversion', - name='dependencies', - field=models.ManyToManyField(related_name='affects', through='oel_publishing.PublishableEntityVersionDependency', to='oel_publishing.publishableentity'), - ), - migrations.CreateModel( - name='PublishSideEffect', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('cause', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='causes', to='oel_publishing.publishlogrecord')), - ('effect', models.ForeignKey(on_delete=django.db.models.deletion.RESTRICT, related_name='affected_by', to='oel_publishing.publishlogrecord')), - ], - options={ - 'verbose_name': 'Publish Side Effect', - 'verbose_name_plural': 'Publish Side Effects', - }, - ), - migrations.AddConstraint( - model_name='publishableentityversiondependency', - constraint=models.UniqueConstraint(fields=('referring_version', 'referenced_entity'), name='oel_pevd_uniq_rv_re'), - ), - migrations.AddConstraint( - model_name='publishsideeffect', - constraint=models.UniqueConstraint(fields=('cause', 'effect'), name='oel_pub_pse_uniq_c_e'), - ), - ] diff --git a/openedx_learning/apps/authoring/publishing/migrations/0010_backfill_dependencies.py b/openedx_learning/apps/authoring/publishing/migrations/0010_backfill_dependencies.py deleted file mode 100644 index c274a401b..000000000 --- a/openedx_learning/apps/authoring/publishing/migrations/0010_backfill_dependencies.py +++ /dev/null @@ -1,149 +0,0 @@ -""" -Backfill PublishableEntityVersionDependency entries based on ContainerVersions. - -We're introducing a lower-level publishing concept of a dependency that will be -used by Containers, but this means we have to backfill that dependency info for -existing Containers in the system. -""" -from django.db import migrations -from django.db.models import F - - -def create_backfill(apps, schema_editor): - """ - Create dependency entries and update dep hashes for Draft and Published. - """ - _create_dependencies(apps) - _update_drafts(apps) - _update_draft_dependencies_hashes(apps) - _update_published_dependencies_hashes(apps) - - -def _create_dependencies(apps): - """ - Populate the PublishableEntityVersion.dependencies relation. - - The only ones we should have in the system at this point are the ones from - containers, so we query ContainerVersion for that. - """ - PublishableEntityVersionDependency = apps.get_model( - "oel_publishing", "PublishableEntityVersionDependency" - ) - ContainerVersion = apps.get_model("oel_publishing", "ContainerVersion") - - for container_version in ContainerVersion.objects.all(): - # child_entity_ids is a set to de-dupe. This doesn't handle pinned - # child references yet, but you can't actually make those in a real - # library yet, so we shouldn't have that data lying around to migrate. - child_entity_ids = set( - container_version - .entity_list - .entitylistrow_set - .all() - .values_list("entity_id", flat=True) - ) - PublishableEntityVersionDependency.objects.bulk_create( - [ - PublishableEntityVersionDependency( - referring_version_id=container_version.pk, - referenced_entity_id=entity_id - ) - for entity_id in child_entity_ids - ], - ignore_conflicts=True, - ) - - -def _update_drafts(apps): - """ - Update Draft entries to point to their most recent DraftLogRecord. - - This is slow and expensive. - """ - Draft = apps.get_model("oel_publishing", "Draft") - DraftChangeLogRecord = apps.get_model("oel_publishing", "DraftChangeLogRecord") - for draft in Draft.objects.all(): - draft_log_record = ( - # Find the most recent DraftChangeLogRecord related to this Draft, - DraftChangeLogRecord.objects - .filter(entity_id=draft.pk) - .order_by('-pk') - .first() - ) - draft.draft_log_record = draft_log_record - draft.save() - - -def _update_draft_dependencies_hashes(apps): - """ - Update the dependency_hash_digest for all DraftChangeLogRecords. - - Backfill dependency state hashes. The important thing here is that things - without dependencies will have the default (blank) state hash, so we only - need to query for Draft entries for Containers. - - We are only backfilling the current DraftChangeLogRecords pointed to by the - Draft entries now. We are not backfilling all historical - DraftChangeLogRecords. Full historical reconstruction is probably possible, - but it's not really worth the cost and complexity. - """ - from ..api import update_dependencies_hash_digests_for_log - from ..models import DraftChangeLog - - # All DraftChangeLogs that have records that are pointed to by the current - # Draft and have a possibility of having dependencies. - change_logs = DraftChangeLog.objects.filter( - pk=F('records__entity__draft__draft_log_record__draft_change_log'), - records__entity__draft__version__isnull=False, - records__entity__container__isnull=False, - ).distinct() - for change_log in change_logs: - update_dependencies_hash_digests_for_log(change_log, backfill=True) - -def _update_published_dependencies_hashes(apps): - """ - Update all container Published.dependencies_hash_digest - - Backfill dependency state hashes. The important thing here is that things - without dependencies will have the default (blank) state hash, so we only - need to query for Published entries for Containers. - """ - from ..api import update_dependencies_hash_digests_for_log - from ..models import PublishLog - - # All PublishLogs that have records that are pointed to by the current - # Published and have a possibility of having dependencies. - change_logs = PublishLog.objects.filter( - pk=F('records__entity__published__publish_log_record__publish_log'), - records__entity__published__version__isnull=False, - records__entity__container__isnull=False, - ).distinct() - for change_log in change_logs: - update_dependencies_hash_digests_for_log(change_log, backfill=True) - -def remove_backfill(apps, schema_editor): - """ - Reset all dep hash values to default ('') and remove dependencies. - """ - Draft = apps.get_model("oel_publishing", "Draft") - DraftChangeLogRecord = apps.get_model("oel_publishing", "DraftChangeLogRecord") - PublishLogRecord = apps.get_model("oel_publishing", "PublishLogRecord") - PublishableEntityVersionDependency = apps.get_model( - "oel_publishing", "PublishableEntityVersionDependency" - ) - - PublishLogRecord.objects.all().update(dependencies_hash_digest='') - DraftChangeLogRecord.objects.all().update(dependencies_hash_digest='') - PublishableEntityVersionDependency.objects.all().delete() - Draft.objects.all().update(draft_log_record=None) - - -class Migration(migrations.Migration): - - dependencies = [ - ('oel_publishing', '0009_dependencies_and_hashing'), - ] - - operations = [ - migrations.RunPython(create_backfill, reverse_code=remove_backfill) - ] diff --git a/openedx_learning/apps/authoring/publishing/migrations/__init__.py b/openedx_learning/apps/authoring/publishing/migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openedx_learning/apps/authoring/publishing/models/container.py b/openedx_learning/apps/authoring/publishing/models/container.py index fc008dd3a..e34bb6a7e 100644 --- a/openedx_learning/apps/authoring/publishing/models/container.py +++ b/openedx_learning/apps/authoring/publishing/models/container.py @@ -23,8 +23,6 @@ class Container(PublishableEntityMixin): PublishLog and Containers that were affected in a publish because their child elements were published. """ - class Meta: - db_table = 'oel_publishing_container' class ContainerVersion(PublishableEntityVersionMixin): @@ -70,6 +68,3 @@ def clean(self): super().clean() if self.container_id != self.publishable_entity_version.entity.container.pk: # pylint: disable=no-member raise ValidationError("Inconsistent foreign keys to Container") - - class Meta: - db_table = 'oel_publishing_containerversion' diff --git a/openedx_learning/apps/authoring/publishing/models/draft_log.py b/openedx_learning/apps/authoring/publishing/models/draft_log.py index 89b58ecbb..ed3eb8731 100644 --- a/openedx_learning/apps/authoring/publishing/models/draft_log.py +++ b/openedx_learning/apps/authoring/publishing/models/draft_log.py @@ -70,9 +70,6 @@ class Draft(models.Model): null=True, ) - class Meta: - db_table = 'oel_publishing_draft' - @property def log_record(self): return self.draft_log_record @@ -143,7 +140,6 @@ class DraftChangeLog(models.Model): ) class Meta: - db_table = 'oel_publishing_draftchangelog' verbose_name = _("Draft Change Log") verbose_name_plural = _("Draft Change Logs") @@ -278,7 +274,6 @@ class DraftChangeLogRecord(models.Model): dependencies_hash_digest = hash_field(blank=True, default='', max_length=8) class Meta: - db_table = 'oel_publishing_draftchangelogrecord' constraints = [ # A PublishableEntity can have only one DraftLogRecord per DraftLog. # You can't simultaneously change the same thing in two different @@ -384,7 +379,6 @@ class DraftSideEffect(models.Model): ) class Meta: - db_table = 'oel_publishing_draftsideeffect' constraints = [ # Duplicate entries for cause & effect are just redundant. This is # here to guard against weird bugs that might introduce this state. diff --git a/openedx_learning/apps/authoring/publishing/models/entity_list.py b/openedx_learning/apps/authoring/publishing/models/entity_list.py index d3da8d8ca..37874acee 100644 --- a/openedx_learning/apps/authoring/publishing/models/entity_list.py +++ b/openedx_learning/apps/authoring/publishing/models/entity_list.py @@ -19,9 +19,6 @@ class EntityList(models.Model): other models, rather than being looked up by their own identifiers. """ - class Meta: - db_table = 'oel_publishing_entitylist' - @cached_property def rows(self): """ @@ -83,7 +80,6 @@ def is_unpinned(self): return self.entity_version_id is None class Meta: - db_table = 'oel_publishing_entitylistrow' ordering = ["order_num"] constraints = [ # If (entity_list, order_num) is not unique, it likely indicates a race condition - so force uniqueness. diff --git a/openedx_learning/apps/authoring/publishing/models/learning_package.py b/openedx_learning/apps/authoring/publishing/models/learning_package.py index 8d3c68003..3ff5bb4bd 100644 --- a/openedx_learning/apps/authoring/publishing/models/learning_package.py +++ b/openedx_learning/apps/authoring/publishing/models/learning_package.py @@ -61,7 +61,6 @@ def __str__(self): return f"{self.key}" class Meta: - db_table = 'oel_publishing_learningpackage' constraints = [ # LearningPackage keys must be globally unique. This is something # that might be relaxed in the future if this system were to be diff --git a/openedx_learning/apps/authoring/publishing/models/publish_log.py b/openedx_learning/apps/authoring/publishing/models/publish_log.py index a5a72702b..d3bc1241f 100644 --- a/openedx_learning/apps/authoring/publishing/models/publish_log.py +++ b/openedx_learning/apps/authoring/publishing/models/publish_log.py @@ -57,7 +57,6 @@ class PublishLog(models.Model): ) class Meta: - db_table = 'oel_publishing_publishlog' verbose_name = "Publish Log" verbose_name_plural = "Publish Logs" @@ -113,7 +112,6 @@ class PublishLogRecord(models.Model): dependencies_hash_digest = hash_field(blank=True, default='', max_length=8) class Meta: - db_table = 'oel_publishing_publishlogrecord' constraints = [ # A Publishable can have only one PublishLogRecord per PublishLog. # You can't simultaneously publish two different versions of the @@ -188,7 +186,6 @@ def log_record(self): return self.publish_log_record class Meta: - db_table = 'oel_publishing_published' verbose_name = "Published Entity" verbose_name_plural = "Published Entities" @@ -227,7 +224,6 @@ class PublishSideEffect(models.Model): ) class Meta: - db_table = 'oel_publishing_publishsideeffect' constraints = [ # Duplicate entries for cause & effect are just redundant. This is # here to guard against weird bugs that might introduce this state. diff --git a/openedx_learning/apps/authoring/publishing/models/publishable_entity.py b/openedx_learning/apps/authoring/publishing/models/publishable_entity.py index a782f8cbf..176735a44 100644 --- a/openedx_learning/apps/authoring/publishing/models/publishable_entity.py +++ b/openedx_learning/apps/authoring/publishing/models/publishable_entity.py @@ -135,7 +135,6 @@ class PublishableEntity(models.Model): ) class Meta: - db_table = 'oel_publishing_publishableentity' constraints = [ # Keys are unique within a given LearningPackage. models.UniqueConstraint( @@ -238,7 +237,6 @@ def __str__(self): return f"{self.entity.key} @ v{self.version_num} - {self.title}" class Meta: - db_table = 'oel_publishing_publishableentityversion' constraints = [ # Prevent the situation where we have multiple # PublishableEntityVersions claiming to be the same version_num for @@ -307,7 +305,6 @@ class PublishableEntityVersionDependency(models.Model): referenced_entity = models.ForeignKey(PublishableEntity, on_delete=models.RESTRICT) class Meta: - db_table = 'oel_publishing_publishableentityversiondependency' constraints = [ models.UniqueConstraint( fields=["referring_version", "referenced_entity"], diff --git a/openedx_learning/apps/authoring/sections/migrations/0001_initial.py b/openedx_learning/apps/authoring/sections/migrations/0001_initial.py deleted file mode 100644 index 5083cda73..000000000 --- a/openedx_learning/apps/authoring/sections/migrations/0001_initial.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 4.2.20 on 2025-04-11 12:53 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('oel_publishing', '0005_alter_entitylistrow_options'), - ] - - operations = [ - migrations.CreateModel( - name='Section', - fields=[ - ('container', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_publishing.container')), - ], - options={ - 'abstract': False, - }, - bases=('oel_publishing.container',), - ), - migrations.CreateModel( - name='SectionVersion', - fields=[ - ('container_version', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_publishing.containerversion')), - ], - options={ - 'abstract': False, - }, - bases=('oel_publishing.containerversion',), - ), - ] diff --git a/openedx_learning/apps/authoring/sections/migrations/__init__.py b/openedx_learning/apps/authoring/sections/migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openedx_learning/apps/authoring/subsections/migrations/0001_initial.py b/openedx_learning/apps/authoring/subsections/migrations/0001_initial.py deleted file mode 100644 index 710c5532b..000000000 --- a/openedx_learning/apps/authoring/subsections/migrations/0001_initial.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 4.2.19 on 2025-04-09 12:59 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('oel_publishing', '0005_alter_entitylistrow_options'), - ] - - operations = [ - migrations.CreateModel( - name='Subsection', - fields=[ - ('container', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_publishing.container')), - ], - options={ - 'abstract': False, - }, - bases=('oel_publishing.container',), - ), - migrations.CreateModel( - name='SubsectionVersion', - fields=[ - ('container_version', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_publishing.containerversion')), - ], - options={ - 'abstract': False, - }, - bases=('oel_publishing.containerversion',), - ), - ] diff --git a/openedx_learning/apps/authoring/subsections/migrations/__init__.py b/openedx_learning/apps/authoring/subsections/migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openedx_learning/apps/authoring/units/migrations/0001_initial.py b/openedx_learning/apps/authoring/units/migrations/0001_initial.py deleted file mode 100644 index 52a5b4fb6..000000000 --- a/openedx_learning/apps/authoring/units/migrations/0001_initial.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 4.2.19 on 2025-03-11 04:31 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('oel_publishing', '0003_containers'), - ] - - operations = [ - migrations.CreateModel( - name='Unit', - fields=[ - ('container', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_publishing.container')), - ], - options={ - 'abstract': False, - }, - bases=('oel_publishing.container',), - ), - migrations.CreateModel( - name='UnitVersion', - fields=[ - ('container_version', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='oel_publishing.containerversion')), - ], - options={ - 'abstract': False, - }, - bases=('oel_publishing.containerversion',), - ), - ] diff --git a/openedx_learning/apps/authoring/units/migrations/__init__.py b/openedx_learning/apps/authoring/units/migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/test_settings.py b/test_settings.py index c4b22926d..33de37081 100644 --- a/test_settings.py +++ b/test_settings.py @@ -18,18 +18,14 @@ def root(*args): DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", - "NAME": "default.db", - "USER": "", - "PASSWORD": "", - "HOST": "", - "PORT": "", + "NAME": ":memory:", } } # If you provision the 'oel'@'%' with broad permissions on your MySQL instance, # running the tests will auto-generate a database for running tests. This is # slower than the default sqlite3 setup above, but it's sometimes helpful for -# finding things that only break in CI. +# finding things that only break in CI. # # DATABASES = { # "default": { @@ -50,20 +46,10 @@ def root(*args): # Admin 'django.contrib.admin', 'django.contrib.admindocs', - # Debugging - "debug_toolbar", # django-rules based authorization 'rules.apps.AutodiscoverRulesConfig', # Our own apps - "openedx_learning.apps.authoring.collections.apps.CollectionsConfig", - "openedx_learning.apps.authoring.components.apps.ComponentsConfig", - "openedx_learning.apps.authoring.contents.apps.ContentsConfig", - "openedx_learning.apps.authoring.publishing.apps.PublishingConfig", - "openedx_tagging.core.tagging.apps.TaggingConfig", - "openedx_learning.apps.authoring.sections.apps.SectionsConfig", - "openedx_learning.apps.authoring.subsections.apps.SubsectionsConfig", - "openedx_learning.apps.authoring.units.apps.UnitsConfig", - "openedx_learning.apps.authoring.backup_restore.apps.BackupRestoreConfig", + "openedx_learning.apps.authoring", ] AUTHENTICATION_BACKENDS = [ From cb4dbeffb7f11e9798bd356c68279f1e7d18a0b3 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Mon, 29 Dec 2025 22:39:34 -0500 Subject: [PATCH 04/13] fix: hacky migration to handle new vs. old installs --- .../apps/authoring/migrations/0001_initial.py | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/openedx_learning/apps/authoring/migrations/0001_initial.py b/openedx_learning/apps/authoring/migrations/0001_initial.py index 5848c05bb..face58e64 100644 --- a/openedx_learning/apps/authoring/migrations/0001_initial.py +++ b/openedx_learning/apps/authoring/migrations/0001_initial.py @@ -1,4 +1,10 @@ -# Generated by Django 5.2.9 on 2025-12-29 06:47 +""" +This migration has two modes it needs to run in: + +1. Existing installs that have migration data that is current through 0.30.2 + (bundled with the Teak release). +2. New installs. +""" import django.core.validators import django.db.models.deletion @@ -10,6 +16,24 @@ from django.db.migrations.operations.special import SeparateDatabaseAndState +class BootstrapMigrations(SeparateDatabaseAndState): + + def __init__(self, operations): + return super().__init__(database_operations=operations, state_operations=operations) + + def has_teak_release_tables(self): + return False + + def database_forwards(self, app_label, schema_editor, from_state, to_state): + if self.has_teak_release_tables(): + return + return super().database_forwards(app_label, schema_editor, from_state, to_state) + + def database_backwards(self, app_label, schema_editor, from_state, to_state): + if self.has_teak_release_tables(): + return + return super().database_backwards(app_label, schema_editor, from_state, to_state) + class Migration(migrations.Migration): initial = True @@ -19,9 +43,8 @@ class Migration(migrations.Migration): ] operations = [ - SeparateDatabaseAndState( - database_operations=[], - state_operations=[ + BootstrapMigrations( + [ migrations.CreateModel( name='PublishableEntity', fields=[ From f0e8e0676860eaa1c9ae35eb039ee8520120f7c4 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Mon, 29 Dec 2025 23:03:33 -0500 Subject: [PATCH 05/13] refactor: make backup_restore work with new layout --- .importlinter | 10 +++++----- .../0016-python-public-api-conventions.rst | 6 +++--- .../management/commands/load_components.py | 6 +++--- openedx_learning/api/authoring.py | 16 ++++++++-------- openedx_learning/api/authoring_models.py | 14 +++++++------- openedx_learning/apps/authoring/admin.py | 16 ++++++++-------- openedx_learning/apps/authoring/apps.py | 12 ++++++------ .../{backup_restore => management}/__init__.py | 0 .../commands}/__init__.py | 0 .../management/commands/lp_dump.py | 4 ++-- .../management/commands/lp_load.py | 2 +- openedx_learning/apps/authoring/models.py | 16 ++++++++-------- .../backup_restore}/__init__.py | 0 .../{ => modules}/backup_restore/admin.py | 0 .../{ => modules}/backup_restore/api.py | 4 ++-- .../{ => modules}/backup_restore/models.py | 0 .../backup_restore/serializers.py | 2 +- .../{ => modules}/backup_restore/toml.py | 8 ++++---- .../{ => modules}/backup_restore/zipper.py | 18 +++++++++--------- .../collections}/__init__.py | 0 .../{ => modules}/collections/admin.py | 0 .../authoring/{ => modules}/collections/api.py | 0 .../{ => modules}/collections/models.py | 0 .../{ => modules}/collections/readme.rst | 0 .../components}/__init__.py | 0 .../{ => modules}/components/admin.py | 0 .../authoring/{ => modules}/components/api.py | 0 .../components/management}/__init__.py | 0 .../management/commands}/__init__.py | 0 .../commands/add_assets_to_component.py | 0 .../{ => modules}/components/models.py | 4 ++-- .../{ => modules}/components/readme.rst | 0 .../commands => modules/contents}/__init__.py | 0 .../authoring/{ => modules}/contents/admin.py | 0 .../authoring/{ => modules}/contents/api.py | 2 +- .../authoring/{ => modules}/contents/models.py | 4 ++-- .../publishing}/__init__.py | 0 .../{ => modules}/publishing/admin.py | 0 .../authoring/{ => modules}/publishing/api.py | 0 .../publishing/contextmanagers.py | 0 .../publishing/models/__init__.py | 0 .../publishing/models/container.py | 0 .../publishing/models/draft_log.py | 0 .../publishing/models/entity_list.py | 0 .../publishing/models/learning_package.py | 0 .../publishing/models/publish_log.py | 0 .../publishing/models/publishable_entity.py | 0 .../{ => modules}/publishing/readme.rst | 0 .../sections}/__init__.py | 0 .../authoring/{ => modules}/sections/admin.py | 0 .../authoring/{ => modules}/sections/api.py | 2 +- .../authoring/{ => modules}/sections/models.py | 0 .../subsections}/__init__.py | 0 .../{ => modules}/subsections/admin.py | 0 .../authoring/{ => modules}/subsections/api.py | 2 +- .../{ => modules}/subsections/models.py | 0 .../{subsections => modules/units}/__init__.py | 0 .../authoring/{ => modules}/units/admin.py | 0 .../apps/authoring/{ => modules}/units/api.py | 3 +-- .../authoring/{ => modules}/units/models.py | 0 .../apps/authoring/units/__init__.py | 0 openedx_learning/contrib/media_server/views.py | 2 +- projects/dev.py | 10 +++++----- .../authoring/backup_restore/test_backup.py | 2 +- .../authoring/backup_restore/test_restore.py | 14 +++++++------- .../authoring/backup_restore/test_slug_hash.py | 2 +- .../apps/authoring/components/test_api.py | 16 ++++++++-------- .../apps/authoring/components/test_assets.py | 10 +++++----- .../apps/authoring/components/test_models.py | 6 +++--- .../authoring/contents/test_file_storage.py | 6 +++--- .../authoring/contents/test_media_types.py | 2 +- .../apps/authoring/publishing/test_api.py | 4 ++-- .../apps/authoring/publishing/test_models.py | 2 +- .../core/tagging/test_system_defined_models.py | 2 +- 74 files changed, 114 insertions(+), 115 deletions(-) rename openedx_learning/apps/authoring/{backup_restore => management}/__init__.py (100%) rename openedx_learning/apps/authoring/{backup_restore/management => management/commands}/__init__.py (100%) rename openedx_learning/apps/authoring/{backup_restore => }/management/commands/lp_dump.py (93%) rename openedx_learning/apps/authoring/{backup_restore => }/management/commands/lp_load.py (95%) rename openedx_learning/apps/authoring/{backup_restore/management/commands => modules/backup_restore}/__init__.py (100%) rename openedx_learning/apps/authoring/{ => modules}/backup_restore/admin.py (100%) rename openedx_learning/apps/authoring/{ => modules}/backup_restore/api.py (84%) rename openedx_learning/apps/authoring/{ => modules}/backup_restore/models.py (100%) rename openedx_learning/apps/authoring/{ => modules}/backup_restore/serializers.py (98%) rename openedx_learning/apps/authoring/{ => modules}/backup_restore/toml.py (95%) rename openedx_learning/apps/authoring/{ => modules}/backup_restore/zipper.py (98%) rename openedx_learning/apps/authoring/{backup_restore/migrations => modules/collections}/__init__.py (100%) rename openedx_learning/apps/authoring/{ => modules}/collections/admin.py (100%) rename openedx_learning/apps/authoring/{ => modules}/collections/api.py (100%) rename openedx_learning/apps/authoring/{ => modules}/collections/models.py (100%) rename openedx_learning/apps/authoring/{ => modules}/collections/readme.rst (100%) rename openedx_learning/apps/authoring/{collections => modules/components}/__init__.py (100%) rename openedx_learning/apps/authoring/{ => modules}/components/admin.py (100%) rename openedx_learning/apps/authoring/{ => modules}/components/api.py (100%) rename openedx_learning/apps/authoring/{components => modules/components/management}/__init__.py (100%) rename openedx_learning/apps/authoring/{components/management => modules/components/management/commands}/__init__.py (100%) rename openedx_learning/apps/authoring/{ => modules}/components/management/commands/add_assets_to_component.py (100%) rename openedx_learning/apps/authoring/{ => modules}/components/models.py (98%) rename openedx_learning/apps/authoring/{ => modules}/components/readme.rst (100%) rename openedx_learning/apps/authoring/{components/management/commands => modules/contents}/__init__.py (100%) rename openedx_learning/apps/authoring/{ => modules}/contents/admin.py (100%) rename openedx_learning/apps/authoring/{ => modules}/contents/api.py (99%) rename openedx_learning/apps/authoring/{ => modules}/contents/models.py (98%) rename openedx_learning/apps/authoring/{contents => modules/publishing}/__init__.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/admin.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/api.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/contextmanagers.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/models/__init__.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/models/container.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/models/draft_log.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/models/entity_list.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/models/learning_package.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/models/publish_log.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/models/publishable_entity.py (100%) rename openedx_learning/apps/authoring/{ => modules}/publishing/readme.rst (100%) rename openedx_learning/apps/authoring/{publishing => modules/sections}/__init__.py (100%) rename openedx_learning/apps/authoring/{ => modules}/sections/admin.py (100%) rename openedx_learning/apps/authoring/{ => modules}/sections/api.py (99%) rename openedx_learning/apps/authoring/{ => modules}/sections/models.py (100%) rename openedx_learning/apps/authoring/{sections => modules/subsections}/__init__.py (100%) rename openedx_learning/apps/authoring/{ => modules}/subsections/admin.py (100%) rename openedx_learning/apps/authoring/{ => modules}/subsections/api.py (99%) rename openedx_learning/apps/authoring/{ => modules}/subsections/models.py (100%) rename openedx_learning/apps/authoring/{subsections => modules/units}/__init__.py (100%) rename openedx_learning/apps/authoring/{ => modules}/units/admin.py (100%) rename openedx_learning/apps/authoring/{ => modules}/units/api.py (99%) rename openedx_learning/apps/authoring/{ => modules}/units/models.py (100%) delete mode 100644 openedx_learning/apps/authoring/units/__init__.py diff --git a/.importlinter b/.importlinter index 6c278d0dd..a6f73a545 100644 --- a/.importlinter +++ b/.importlinter @@ -36,24 +36,24 @@ layers= openedx_learning.api.authoring # The "backup_restore" app handle the new export and import mechanism. - openedx_learning.apps.authoring.backup_restore + openedx_learning.apps.authoring.modules.backup_restore # The "components" app is responsible for storing versioned Components, # which is Open edX Studio terminology maps to things like individual # Problems, Videos, and blocks of HTML text. This is also the type we would # associate with a single "leaf" XBlock–one that is not a container type and # has no child elements. - openedx_learning.apps.authoring.components + openedx_learning.apps.authoring.modules.components # The "contents" app stores the simplest pieces of binary and text data, # without versioning information. These belong to a single Learning Package. - openedx_learning.apps.authoring.contents + openedx_learning.apps.authoring.modules.contents # The "collections" app stores arbitrary groupings of PublishableEntities. # Its only dependency should be the publishing app. - openedx_learning.apps.authoring.collections + openedx_learning.apps.authoring.modules.collections # The lowest layer is "publishing", which holds the basic primitives needed # to create Learning Packages and manage the draft and publish states for # various types of content. - openedx_learning.apps.authoring.publishing + openedx_learning.apps.authoring.modules.publishing diff --git a/docs/decisions/0016-python-public-api-conventions.rst b/docs/decisions/0016-python-public-api-conventions.rst index 20bb1f766..d60aa2620 100644 --- a/docs/decisions/0016-python-public-api-conventions.rst +++ b/docs/decisions/0016-python-public-api-conventions.rst @@ -20,7 +20,7 @@ Learning Core Django apps will be grouped into packages. Apps in ``openedx_learning`` will be grouped into broadly related packages under ``openedx_learning.apps``. The first of these groups will be "authoring" (``openedx_learning.apps.authoring``). Future packages may include "learner", "personalization", "activity", "grading", etc. Learning Core Django apps will continue to have their own ``api`` modules. - So for example, ``openedx_learning.apps.authoring.components.api`` will continue to exist. + So for example, ``openedx_learning.apps.authoring.modules.components.api`` will continue to exist. Learning Core will have a top level package for its public API. All public APIs intended for use by consumers of Learning Core will be represented as modules in the ``openedx_learning.api`` package that corresponds to the app groupings (e.g. ``openedx_learning.api.authoring``). @@ -35,14 +35,14 @@ App ``api`` modules will define their public functions using ``__all__``. This relies on the individual apps to properly set ``__all__`` to the list of functions that they are willing to publicly support. App ``api`` modules within a package of apps still import from each other. - So for example, ``openedx_learning.apps.authoring.components.api`` will continue to import APIs that it needs from ``..publishing.api``, instead of using the public API at ``openedx_learning.api.authoring``. These imports should not use wildcards. + So for example, ``openedx_learning.apps.authoring.modules.components.api`` will continue to import APIs that it needs from ``..publishing.api``, instead of using the public API at ``openedx_learning.api.authoring``. These imports should not use wildcards. Functions and constants that are not listed as part of a module's ``__all__`` may still be imported by other app APIs in the same package grouping. This should allow a package more flexibility to create provisional APIs that we may not want to support publicly. If a function or attribute is intended to be completely private to an app's ``api`` module (i.e. not used even by other apps in its package), it should be prefixed with an underscore. App ``api`` modules should not import directly from apps outside their package. - For example, ``openedx_learning.apps.personalization.api`` should import authoring API functions from ``openedx_learning.api.authoring``, **not** directly from something like ``openedx_learning.apps.authoring.components.api``. This will help to limit the impact of refactoring app package internal changes, as well as exposing shortcomings in the existing public APIs. + For example, ``openedx_learning.apps.personalization.api`` should import authoring API functions from ``openedx_learning.api.authoring``, **not** directly from something like ``openedx_learning.apps.authoring.modules.components.api``. This will help to limit the impact of refactoring app package internal changes, as well as exposing shortcomings in the existing public APIs. Public API modules may implement their own functions. In addition to aggregating app ``api`` modules via wildcard imports, public API modules like ``openedx_learning.api.authoring`` may implement their own functionality. This will be useful for convenience functions that invoke multiple app APIs, and for backwards compatibility shims. When possible, the bulk of the logic for these should continue to live in app-defined APIs, with the public API module acting more as a glue layer. diff --git a/olx_importer/management/commands/load_components.py b/olx_importer/management/commands/load_components.py index 55cd268c8..3ec871d4b 100644 --- a/olx_importer/management/commands/load_components.py +++ b/olx_importer/management/commands/load_components.py @@ -28,9 +28,9 @@ from django.db import transaction # Model references to remove -from openedx_learning.apps.authoring.components import api as components_api -from openedx_learning.apps.authoring.contents import api as contents_api -from openedx_learning.apps.authoring.publishing import api as publishing_api +from openedx_learning.apps.authoring.modules.components import api as components_api +from openedx_learning.apps.authoring.modules.contents import api as contents_api +from openedx_learning.apps.authoring.modules.publishing import api as publishing_api SUPPORTED_TYPES = ["problem", "video", "html"] logger = logging.getLogger(__name__) diff --git a/openedx_learning/api/authoring.py b/openedx_learning/api/authoring.py index 9082b33fb..c6799b6c1 100644 --- a/openedx_learning/api/authoring.py +++ b/openedx_learning/api/authoring.py @@ -9,14 +9,14 @@ """ # These wildcard imports are okay because these api modules declare __all__. # pylint: disable=wildcard-import -from ..apps.authoring.backup_restore.api import * -from ..apps.authoring.collections.api import * -from ..apps.authoring.components.api import * -from ..apps.authoring.contents.api import * -from ..apps.authoring.publishing.api import * -from ..apps.authoring.sections.api import * -from ..apps.authoring.subsections.api import * -from ..apps.authoring.units.api import * +from ..apps.authoring.modules.backup_restore.api import * +from ..apps.authoring.modules.collections.api import * +from ..apps.authoring.modules.components.api import * +from ..apps.authoring.modules.contents.api import * +from ..apps.authoring.modules.publishing.api import * +from ..apps.authoring.modules.sections.api import * +from ..apps.authoring.modules.subsections.api import * +from ..apps.authoring.modules.units.api import * # This was renamed after the authoring API refactoring pushed this and other # app APIs into the openedx_learning.api.authoring module. Here I'm aliasing to diff --git a/openedx_learning/api/authoring_models.py b/openedx_learning/api/authoring_models.py index 617d85dc4..df7180cdd 100644 --- a/openedx_learning/api/authoring_models.py +++ b/openedx_learning/api/authoring_models.py @@ -7,10 +7,10 @@ """ # These wildcard imports are okay because these modules declare __all__. # pylint: disable=wildcard-import -from ..apps.authoring.collections.models import * -from ..apps.authoring.components.models import * -from ..apps.authoring.contents.models import * -from ..apps.authoring.publishing.models import * -from ..apps.authoring.sections.models import * -from ..apps.authoring.subsections.models import * -from ..apps.authoring.units.models import * +from ..apps.authoring.modules.collections.models import * +from ..apps.authoring.modules.components.models import * +from ..apps.authoring.modules.contents.models import * +from ..apps.authoring.modules.publishing.models import * +from ..apps.authoring.modules.sections.models import * +from ..apps.authoring.modules.subsections.models import * +from ..apps.authoring.modules.units.models import * diff --git a/openedx_learning/apps/authoring/admin.py b/openedx_learning/apps/authoring/admin.py index ff67ae96f..fc349cb3e 100644 --- a/openedx_learning/apps/authoring/admin.py +++ b/openedx_learning/apps/authoring/admin.py @@ -1,8 +1,8 @@ -from .backup_restore.admin import * -from .collections.admin import * -from .components.admin import * -from .contents.admin import * -from .publishing.admin import * -from .sections.admin import * -from .subsections.admin import * -from .units.admin import * \ No newline at end of file +from .modules.backup_restore.admin import * +from .modules.collections.admin import * +from .modules.components.admin import * +from .modules.contents.admin import * +from .modules.publishing.admin import * +from .modules.sections.admin import * +from .modules.subsections.admin import * +from .modules.units.admin import * \ No newline at end of file diff --git a/openedx_learning/apps/authoring/apps.py b/openedx_learning/apps/authoring/apps.py index 26bd01d24..98c544324 100644 --- a/openedx_learning/apps/authoring/apps.py +++ b/openedx_learning/apps/authoring/apps.py @@ -7,13 +7,13 @@ class AuthoringConfig(AppConfig): label = "oel_authoring" def ready(self): - from .publishing.api import register_publishable_models + from .modules.publishing.api import register_publishable_models - from .components.models import Component, ComponentVersion - from .publishing.models import Container, ContainerVersion - from .sections.models import Section, SectionVersion - from .subsections.models import Subsection, SubsectionVersion - from .units.models import Unit, UnitVersion + from .modules.components.models import Component, ComponentVersion + from .modules.publishing.models import Container, ContainerVersion + from .modules.sections.models import Section, SectionVersion + from .modules.subsections.models import Subsection, SubsectionVersion + from .modules.units.models import Unit, UnitVersion register_publishable_models(Component, ComponentVersion) register_publishable_models(Container, ContainerVersion) diff --git a/openedx_learning/apps/authoring/backup_restore/__init__.py b/openedx_learning/apps/authoring/management/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/backup_restore/__init__.py rename to openedx_learning/apps/authoring/management/__init__.py diff --git a/openedx_learning/apps/authoring/backup_restore/management/__init__.py b/openedx_learning/apps/authoring/management/commands/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/backup_restore/management/__init__.py rename to openedx_learning/apps/authoring/management/commands/__init__.py diff --git a/openedx_learning/apps/authoring/backup_restore/management/commands/lp_dump.py b/openedx_learning/apps/authoring/management/commands/lp_dump.py similarity index 93% rename from openedx_learning/apps/authoring/backup_restore/management/commands/lp_dump.py rename to openedx_learning/apps/authoring/management/commands/lp_dump.py index b1fb52b4e..c74f9450d 100644 --- a/openedx_learning/apps/authoring/backup_restore/management/commands/lp_dump.py +++ b/openedx_learning/apps/authoring/management/commands/lp_dump.py @@ -8,8 +8,8 @@ from django.core.management import CommandError from django.core.management.base import BaseCommand -from openedx_learning.apps.authoring.backup_restore.api import create_zip_file -from openedx_learning.apps.authoring.publishing.api import LearningPackage +from openedx_learning.apps.authoring.modules.backup_restore.api import create_zip_file +from openedx_learning.apps.authoring.modules.publishing.api import LearningPackage logger = logging.getLogger(__name__) diff --git a/openedx_learning/apps/authoring/backup_restore/management/commands/lp_load.py b/openedx_learning/apps/authoring/management/commands/lp_load.py similarity index 95% rename from openedx_learning/apps/authoring/backup_restore/management/commands/lp_load.py rename to openedx_learning/apps/authoring/management/commands/lp_load.py index a326a0850..cd741beb4 100644 --- a/openedx_learning/apps/authoring/backup_restore/management/commands/lp_load.py +++ b/openedx_learning/apps/authoring/management/commands/lp_load.py @@ -8,7 +8,7 @@ from django.core.management import CommandError from django.core.management.base import BaseCommand -from openedx_learning.apps.authoring.backup_restore.api import load_learning_package +from openedx_learning.apps.authoring.modules.backup_restore.api import load_learning_package logger = logging.getLogger(__name__) diff --git a/openedx_learning/apps/authoring/models.py b/openedx_learning/apps/authoring/models.py index 5965c8b1c..4c729dd71 100644 --- a/openedx_learning/apps/authoring/models.py +++ b/openedx_learning/apps/authoring/models.py @@ -1,8 +1,8 @@ -from .backup_restore.models import * -from .collections.models import * -from .components.models import * -from .contents.models import * -from .publishing.models import * -from .sections.models import * -from .subsections.models import * -from .units.models import * +from .modules.backup_restore.models import * +from .modules.collections.models import * +from .modules.components.models import * +from .modules.contents.models import * +from .modules.publishing.models import * +from .modules.sections.models import * +from .modules.subsections.models import * +from .modules.units.models import * diff --git a/openedx_learning/apps/authoring/backup_restore/management/commands/__init__.py b/openedx_learning/apps/authoring/modules/backup_restore/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/backup_restore/management/commands/__init__.py rename to openedx_learning/apps/authoring/modules/backup_restore/__init__.py diff --git a/openedx_learning/apps/authoring/backup_restore/admin.py b/openedx_learning/apps/authoring/modules/backup_restore/admin.py similarity index 100% rename from openedx_learning/apps/authoring/backup_restore/admin.py rename to openedx_learning/apps/authoring/modules/backup_restore/admin.py diff --git a/openedx_learning/apps/authoring/backup_restore/api.py b/openedx_learning/apps/authoring/modules/backup_restore/api.py similarity index 84% rename from openedx_learning/apps/authoring/backup_restore/api.py rename to openedx_learning/apps/authoring/modules/backup_restore/api.py index 802bf6ff3..097d86f89 100644 --- a/openedx_learning/apps/authoring/backup_restore/api.py +++ b/openedx_learning/apps/authoring/modules/backup_restore/api.py @@ -5,8 +5,8 @@ from django.contrib.auth.models import User as UserType # pylint: disable=imported-auth-user -from openedx_learning.apps.authoring.backup_restore.zipper import LearningPackageUnzipper, LearningPackageZipper -from openedx_learning.apps.authoring.publishing.api import get_learning_package_by_key +from .zipper import LearningPackageUnzipper, LearningPackageZipper +from ..publishing.api import get_learning_package_by_key def create_zip_file(lp_key: str, path: str, user: UserType | None = None, origin_server: str | None = None) -> None: diff --git a/openedx_learning/apps/authoring/backup_restore/models.py b/openedx_learning/apps/authoring/modules/backup_restore/models.py similarity index 100% rename from openedx_learning/apps/authoring/backup_restore/models.py rename to openedx_learning/apps/authoring/modules/backup_restore/models.py diff --git a/openedx_learning/apps/authoring/backup_restore/serializers.py b/openedx_learning/apps/authoring/modules/backup_restore/serializers.py similarity index 98% rename from openedx_learning/apps/authoring/backup_restore/serializers.py rename to openedx_learning/apps/authoring/modules/backup_restore/serializers.py index c34e81059..d8f7a5c15 100644 --- a/openedx_learning/apps/authoring/backup_restore/serializers.py +++ b/openedx_learning/apps/authoring/modules/backup_restore/serializers.py @@ -5,7 +5,7 @@ from rest_framework import serializers -from openedx_learning.apps.authoring.components import api as components_api +from ..components import api as components_api class LearningPackageSerializer(serializers.Serializer): # pylint: disable=abstract-method diff --git a/openedx_learning/apps/authoring/backup_restore/toml.py b/openedx_learning/apps/authoring/modules/backup_restore/toml.py similarity index 95% rename from openedx_learning/apps/authoring/backup_restore/toml.py rename to openedx_learning/apps/authoring/modules/backup_restore/toml.py index a3ab9a03d..a75e7a0ad 100644 --- a/openedx_learning/apps/authoring/backup_restore/toml.py +++ b/openedx_learning/apps/authoring/modules/backup_restore/toml.py @@ -8,10 +8,10 @@ import tomlkit from django.contrib.auth.models import User as UserType # pylint: disable=imported-auth-user -from openedx_learning.apps.authoring.collections.models import Collection -from openedx_learning.apps.authoring.publishing import api as publishing_api -from openedx_learning.apps.authoring.publishing.models import PublishableEntity, PublishableEntityVersion -from openedx_learning.apps.authoring.publishing.models.learning_package import LearningPackage +from ..collections.models import Collection +from ..publishing import api as publishing_api +from ..publishing.models import PublishableEntity, PublishableEntityVersion +from ..publishing.models.learning_package import LearningPackage def toml_learning_package( diff --git a/openedx_learning/apps/authoring/backup_restore/zipper.py b/openedx_learning/apps/authoring/modules/backup_restore/zipper.py similarity index 98% rename from openedx_learning/apps/authoring/backup_restore/zipper.py rename to openedx_learning/apps/authoring/modules/backup_restore/zipper.py index 27ddcacc3..4040983ae 100644 --- a/openedx_learning/apps/authoring/backup_restore/zipper.py +++ b/openedx_learning/apps/authoring/modules/backup_restore/zipper.py @@ -28,7 +28,7 @@ PublishableEntity, PublishableEntityVersion, ) -from openedx_learning.apps.authoring.backup_restore.serializers import ( +from .serializers import ( CollectionSerializer, ComponentSerializer, ComponentVersionSerializer, @@ -37,7 +37,7 @@ LearningPackageMetadataSerializer, LearningPackageSerializer, ) -from openedx_learning.apps.authoring.backup_restore.toml import ( +from .toml import ( parse_collection_toml, parse_learning_package_toml, parse_publishable_entity_toml, @@ -45,13 +45,13 @@ toml_learning_package, toml_publishable_entity, ) -from openedx_learning.apps.authoring.collections import api as collections_api -from openedx_learning.apps.authoring.components import api as components_api -from openedx_learning.apps.authoring.contents import api as contents_api -from openedx_learning.apps.authoring.publishing import api as publishing_api -from openedx_learning.apps.authoring.sections import api as sections_api -from openedx_learning.apps.authoring.subsections import api as subsections_api -from openedx_learning.apps.authoring.units import api as units_api +from ..collections import api as collections_api +from ..components import api as components_api +from ..contents import api as contents_api +from ..publishing import api as publishing_api +from ..sections import api as sections_api +from ..subsections import api as subsections_api +from ..units import api as units_api TOML_PACKAGE_NAME = "package.toml" DEFAULT_USERNAME = "command" diff --git a/openedx_learning/apps/authoring/backup_restore/migrations/__init__.py b/openedx_learning/apps/authoring/modules/collections/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/backup_restore/migrations/__init__.py rename to openedx_learning/apps/authoring/modules/collections/__init__.py diff --git a/openedx_learning/apps/authoring/collections/admin.py b/openedx_learning/apps/authoring/modules/collections/admin.py similarity index 100% rename from openedx_learning/apps/authoring/collections/admin.py rename to openedx_learning/apps/authoring/modules/collections/admin.py diff --git a/openedx_learning/apps/authoring/collections/api.py b/openedx_learning/apps/authoring/modules/collections/api.py similarity index 100% rename from openedx_learning/apps/authoring/collections/api.py rename to openedx_learning/apps/authoring/modules/collections/api.py diff --git a/openedx_learning/apps/authoring/collections/models.py b/openedx_learning/apps/authoring/modules/collections/models.py similarity index 100% rename from openedx_learning/apps/authoring/collections/models.py rename to openedx_learning/apps/authoring/modules/collections/models.py diff --git a/openedx_learning/apps/authoring/collections/readme.rst b/openedx_learning/apps/authoring/modules/collections/readme.rst similarity index 100% rename from openedx_learning/apps/authoring/collections/readme.rst rename to openedx_learning/apps/authoring/modules/collections/readme.rst diff --git a/openedx_learning/apps/authoring/collections/__init__.py b/openedx_learning/apps/authoring/modules/components/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/collections/__init__.py rename to openedx_learning/apps/authoring/modules/components/__init__.py diff --git a/openedx_learning/apps/authoring/components/admin.py b/openedx_learning/apps/authoring/modules/components/admin.py similarity index 100% rename from openedx_learning/apps/authoring/components/admin.py rename to openedx_learning/apps/authoring/modules/components/admin.py diff --git a/openedx_learning/apps/authoring/components/api.py b/openedx_learning/apps/authoring/modules/components/api.py similarity index 100% rename from openedx_learning/apps/authoring/components/api.py rename to openedx_learning/apps/authoring/modules/components/api.py diff --git a/openedx_learning/apps/authoring/components/__init__.py b/openedx_learning/apps/authoring/modules/components/management/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/components/__init__.py rename to openedx_learning/apps/authoring/modules/components/management/__init__.py diff --git a/openedx_learning/apps/authoring/components/management/__init__.py b/openedx_learning/apps/authoring/modules/components/management/commands/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/components/management/__init__.py rename to openedx_learning/apps/authoring/modules/components/management/commands/__init__.py diff --git a/openedx_learning/apps/authoring/components/management/commands/add_assets_to_component.py b/openedx_learning/apps/authoring/modules/components/management/commands/add_assets_to_component.py similarity index 100% rename from openedx_learning/apps/authoring/components/management/commands/add_assets_to_component.py rename to openedx_learning/apps/authoring/modules/components/management/commands/add_assets_to_component.py diff --git a/openedx_learning/apps/authoring/components/models.py b/openedx_learning/apps/authoring/modules/components/models.py similarity index 98% rename from openedx_learning/apps/authoring/components/models.py rename to openedx_learning/apps/authoring/modules/components/models.py index 966a9d2fb..340aa2505 100644 --- a/openedx_learning/apps/authoring/components/models.py +++ b/openedx_learning/apps/authoring/modules/components/models.py @@ -21,8 +21,8 @@ from django.db import models -from ....lib.fields import case_sensitive_char_field, key_field -from ....lib.managers import WithRelationsManager +from openedx_learning.lib.fields import case_sensitive_char_field, key_field +from openedx_learning.lib.managers import WithRelationsManager from ..contents.models import Content from ..publishing.models import LearningPackage, PublishableEntityMixin, PublishableEntityVersionMixin diff --git a/openedx_learning/apps/authoring/components/readme.rst b/openedx_learning/apps/authoring/modules/components/readme.rst similarity index 100% rename from openedx_learning/apps/authoring/components/readme.rst rename to openedx_learning/apps/authoring/modules/components/readme.rst diff --git a/openedx_learning/apps/authoring/components/management/commands/__init__.py b/openedx_learning/apps/authoring/modules/contents/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/components/management/commands/__init__.py rename to openedx_learning/apps/authoring/modules/contents/__init__.py diff --git a/openedx_learning/apps/authoring/contents/admin.py b/openedx_learning/apps/authoring/modules/contents/admin.py similarity index 100% rename from openedx_learning/apps/authoring/contents/admin.py rename to openedx_learning/apps/authoring/modules/contents/admin.py diff --git a/openedx_learning/apps/authoring/contents/api.py b/openedx_learning/apps/authoring/modules/contents/api.py similarity index 99% rename from openedx_learning/apps/authoring/contents/api.py rename to openedx_learning/apps/authoring/modules/contents/api.py index 319935882..ed8251e53 100644 --- a/openedx_learning/apps/authoring/contents/api.py +++ b/openedx_learning/apps/authoring/modules/contents/api.py @@ -12,7 +12,7 @@ from django.core.files.base import ContentFile from django.db.transaction import atomic -from ....lib.fields import create_hash_digest +from openedx_learning.lib.fields import create_hash_digest from .models import Content, MediaType # The public API that will be re-exported by openedx_learning.apps.authoring.api diff --git a/openedx_learning/apps/authoring/contents/models.py b/openedx_learning/apps/authoring/modules/contents/models.py similarity index 98% rename from openedx_learning/apps/authoring/contents/models.py rename to openedx_learning/apps/authoring/modules/contents/models.py index c087c122f..dc2dd1829 100644 --- a/openedx_learning/apps/authoring/contents/models.py +++ b/openedx_learning/apps/authoring/modules/contents/models.py @@ -16,8 +16,8 @@ from django.db import models from django.utils.module_loading import import_string -from ....lib.fields import MultiCollationTextField, case_insensitive_char_field, hash_field, manual_date_time_field -from ....lib.managers import WithRelationsManager +from openedx_learning.lib.fields import MultiCollationTextField, case_insensitive_char_field, hash_field, manual_date_time_field +from openedx_learning.lib.managers import WithRelationsManager from ..publishing.models import LearningPackage logger = getLogger() diff --git a/openedx_learning/apps/authoring/contents/__init__.py b/openedx_learning/apps/authoring/modules/publishing/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/contents/__init__.py rename to openedx_learning/apps/authoring/modules/publishing/__init__.py diff --git a/openedx_learning/apps/authoring/publishing/admin.py b/openedx_learning/apps/authoring/modules/publishing/admin.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/admin.py rename to openedx_learning/apps/authoring/modules/publishing/admin.py diff --git a/openedx_learning/apps/authoring/publishing/api.py b/openedx_learning/apps/authoring/modules/publishing/api.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/api.py rename to openedx_learning/apps/authoring/modules/publishing/api.py diff --git a/openedx_learning/apps/authoring/publishing/contextmanagers.py b/openedx_learning/apps/authoring/modules/publishing/contextmanagers.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/contextmanagers.py rename to openedx_learning/apps/authoring/modules/publishing/contextmanagers.py diff --git a/openedx_learning/apps/authoring/publishing/models/__init__.py b/openedx_learning/apps/authoring/modules/publishing/models/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/models/__init__.py rename to openedx_learning/apps/authoring/modules/publishing/models/__init__.py diff --git a/openedx_learning/apps/authoring/publishing/models/container.py b/openedx_learning/apps/authoring/modules/publishing/models/container.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/models/container.py rename to openedx_learning/apps/authoring/modules/publishing/models/container.py diff --git a/openedx_learning/apps/authoring/publishing/models/draft_log.py b/openedx_learning/apps/authoring/modules/publishing/models/draft_log.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/models/draft_log.py rename to openedx_learning/apps/authoring/modules/publishing/models/draft_log.py diff --git a/openedx_learning/apps/authoring/publishing/models/entity_list.py b/openedx_learning/apps/authoring/modules/publishing/models/entity_list.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/models/entity_list.py rename to openedx_learning/apps/authoring/modules/publishing/models/entity_list.py diff --git a/openedx_learning/apps/authoring/publishing/models/learning_package.py b/openedx_learning/apps/authoring/modules/publishing/models/learning_package.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/models/learning_package.py rename to openedx_learning/apps/authoring/modules/publishing/models/learning_package.py diff --git a/openedx_learning/apps/authoring/publishing/models/publish_log.py b/openedx_learning/apps/authoring/modules/publishing/models/publish_log.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/models/publish_log.py rename to openedx_learning/apps/authoring/modules/publishing/models/publish_log.py diff --git a/openedx_learning/apps/authoring/publishing/models/publishable_entity.py b/openedx_learning/apps/authoring/modules/publishing/models/publishable_entity.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/models/publishable_entity.py rename to openedx_learning/apps/authoring/modules/publishing/models/publishable_entity.py diff --git a/openedx_learning/apps/authoring/publishing/readme.rst b/openedx_learning/apps/authoring/modules/publishing/readme.rst similarity index 100% rename from openedx_learning/apps/authoring/publishing/readme.rst rename to openedx_learning/apps/authoring/modules/publishing/readme.rst diff --git a/openedx_learning/apps/authoring/publishing/__init__.py b/openedx_learning/apps/authoring/modules/sections/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/publishing/__init__.py rename to openedx_learning/apps/authoring/modules/sections/__init__.py diff --git a/openedx_learning/apps/authoring/sections/admin.py b/openedx_learning/apps/authoring/modules/sections/admin.py similarity index 100% rename from openedx_learning/apps/authoring/sections/admin.py rename to openedx_learning/apps/authoring/modules/sections/admin.py diff --git a/openedx_learning/apps/authoring/sections/api.py b/openedx_learning/apps/authoring/modules/sections/api.py similarity index 99% rename from openedx_learning/apps/authoring/sections/api.py rename to openedx_learning/apps/authoring/modules/sections/api.py index f6d58b858..589636075 100644 --- a/openedx_learning/apps/authoring/sections/api.py +++ b/openedx_learning/apps/authoring/modules/sections/api.py @@ -7,7 +7,7 @@ from django.db.transaction import atomic -from openedx_learning.apps.authoring.subsections.models import Subsection, SubsectionVersion +from ..subsections.models import Subsection, SubsectionVersion from ..publishing import api as publishing_api from .models import Section, SectionVersion diff --git a/openedx_learning/apps/authoring/sections/models.py b/openedx_learning/apps/authoring/modules/sections/models.py similarity index 100% rename from openedx_learning/apps/authoring/sections/models.py rename to openedx_learning/apps/authoring/modules/sections/models.py diff --git a/openedx_learning/apps/authoring/sections/__init__.py b/openedx_learning/apps/authoring/modules/subsections/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/sections/__init__.py rename to openedx_learning/apps/authoring/modules/subsections/__init__.py diff --git a/openedx_learning/apps/authoring/subsections/admin.py b/openedx_learning/apps/authoring/modules/subsections/admin.py similarity index 100% rename from openedx_learning/apps/authoring/subsections/admin.py rename to openedx_learning/apps/authoring/modules/subsections/admin.py diff --git a/openedx_learning/apps/authoring/subsections/api.py b/openedx_learning/apps/authoring/modules/subsections/api.py similarity index 99% rename from openedx_learning/apps/authoring/subsections/api.py rename to openedx_learning/apps/authoring/modules/subsections/api.py index 02c1edf93..97a9e3ff2 100644 --- a/openedx_learning/apps/authoring/subsections/api.py +++ b/openedx_learning/apps/authoring/modules/subsections/api.py @@ -7,7 +7,7 @@ from django.db.transaction import atomic -from openedx_learning.apps.authoring.units.models import Unit, UnitVersion +from ..units.models import Unit, UnitVersion from ..publishing import api as publishing_api from .models import Subsection, SubsectionVersion diff --git a/openedx_learning/apps/authoring/subsections/models.py b/openedx_learning/apps/authoring/modules/subsections/models.py similarity index 100% rename from openedx_learning/apps/authoring/subsections/models.py rename to openedx_learning/apps/authoring/modules/subsections/models.py diff --git a/openedx_learning/apps/authoring/subsections/__init__.py b/openedx_learning/apps/authoring/modules/units/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/subsections/__init__.py rename to openedx_learning/apps/authoring/modules/units/__init__.py diff --git a/openedx_learning/apps/authoring/units/admin.py b/openedx_learning/apps/authoring/modules/units/admin.py similarity index 100% rename from openedx_learning/apps/authoring/units/admin.py rename to openedx_learning/apps/authoring/modules/units/admin.py diff --git a/openedx_learning/apps/authoring/units/api.py b/openedx_learning/apps/authoring/modules/units/api.py similarity index 99% rename from openedx_learning/apps/authoring/units/api.py rename to openedx_learning/apps/authoring/modules/units/api.py index ca9a2468d..779b5b3d0 100644 --- a/openedx_learning/apps/authoring/units/api.py +++ b/openedx_learning/apps/authoring/modules/units/api.py @@ -7,8 +7,7 @@ from django.db.transaction import atomic -from openedx_learning.apps.authoring.components.models import Component, ComponentVersion - +from ..components.models import Component, ComponentVersion from ..publishing import api as publishing_api from .models import Unit, UnitVersion diff --git a/openedx_learning/apps/authoring/units/models.py b/openedx_learning/apps/authoring/modules/units/models.py similarity index 100% rename from openedx_learning/apps/authoring/units/models.py rename to openedx_learning/apps/authoring/modules/units/models.py diff --git a/openedx_learning/apps/authoring/units/__init__.py b/openedx_learning/apps/authoring/units/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openedx_learning/contrib/media_server/views.py b/openedx_learning/contrib/media_server/views.py index d7088879e..5fdf7deb0 100644 --- a/openedx_learning/contrib/media_server/views.py +++ b/openedx_learning/contrib/media_server/views.py @@ -8,7 +8,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.http import FileResponse, Http404 -from openedx_learning.apps.authoring.components.api import look_up_component_version_content +from openedx_learning.apps.authoring.modules.components.api import look_up_component_version_content def component_asset( diff --git a/projects/dev.py b/projects/dev.py index 082a300d2..05bd2f649 100644 --- a/projects/dev.py +++ b/projects/dev.py @@ -34,14 +34,14 @@ "openedx_learning.apps.authoring", - #"openedx_learning.apps.authoring.collections", - #"openedx_learning.apps.authoring.components", - #"openedx_learning.apps.authoring.contents", - #"openedx_learning.apps.authoring.publishing", + #"openedx_learning.apps.authoring.modules.collections", + #"openedx_learning.apps.authoring.modules.components", + #"openedx_learning.apps.authoring.modules.contents", + #"openedx_learning.apps.authoring.modules.publishing", #"openedx_learning.apps.authoring.sections", #"openedx_learning.apps.authoring.subsections", #"openedx_learning.apps.authoring.units", - #"openedx_learning.apps.authoring.backup_restore", + #"openedx_learning.apps.authoring.modules.backup_restore", # Learning Contrib Apps # "openedx_learning.contrib.media_server.apps.MediaServerConfig", diff --git a/tests/openedx_learning/apps/authoring/backup_restore/test_backup.py b/tests/openedx_learning/apps/authoring/backup_restore/test_backup.py index 312f289f1..b77be9740 100644 --- a/tests/openedx_learning/apps/authoring/backup_restore/test_backup.py +++ b/tests/openedx_learning/apps/authoring/backup_restore/test_backup.py @@ -12,7 +12,7 @@ from openedx_learning.api import authoring as api from openedx_learning.api.authoring_models import Collection, Component, Content, LearningPackage, PublishableEntity -from openedx_learning.apps.authoring.backup_restore.zipper import LearningPackageZipper +from openedx_learning.apps.authoring.modules.backup_restore.zipper import LearningPackageZipper from openedx_learning.lib.test_utils import TestCase User = get_user_model() diff --git a/tests/openedx_learning/apps/authoring/backup_restore/test_restore.py b/tests/openedx_learning/apps/authoring/backup_restore/test_restore.py index e34a0b5f7..287610b4f 100644 --- a/tests/openedx_learning/apps/authoring/backup_restore/test_restore.py +++ b/tests/openedx_learning/apps/authoring/backup_restore/test_restore.py @@ -7,10 +7,10 @@ from django.contrib.auth import get_user_model from django.core.management import call_command -from openedx_learning.apps.authoring.backup_restore.zipper import LearningPackageUnzipper, generate_staged_lp_key -from openedx_learning.apps.authoring.collections import api as collections_api -from openedx_learning.apps.authoring.components import api as components_api -from openedx_learning.apps.authoring.publishing import api as publishing_api +from openedx_learning.apps.authoring.modules.backup_restore.zipper import LearningPackageUnzipper, generate_staged_lp_key +from openedx_learning.apps.authoring.modules.collections import api as collections_api +from openedx_learning.apps.authoring.modules.components import api as components_api +from openedx_learning.apps.authoring.modules.publishing import api as publishing_api from openedx_learning.lib.test_utils import TestCase from test_utils.zip_file_utils import folder_to_inmemory_zip @@ -31,7 +31,7 @@ def setUp(self): class RestoreLearningPackageCommandTest(RestoreTestCase): """Tests for the lp_load management command.""" - @patch("openedx_learning.apps.authoring.backup_restore.api.load_learning_package") + @patch("openedx_learning.apps.authoring.modules.backup_restore.api.load_learning_package") def test_restore_command(self, mock_load_learning_package): # Mock load_learning_package to return our in-memory zip file restore_result = LearningPackageUnzipper(self.zip_file, user=self.user).load() @@ -284,7 +284,7 @@ def test_error_learning_package_missing_key(self): # Mock parse_learning_package_toml to return a dict without 'key' with patch( - "openedx_learning.apps.authoring.backup_restore.zipper.parse_learning_package_toml", + "openedx_learning.apps.authoring.modules.backup_restore.zipper.parse_learning_package_toml", return_value={ "learning_package": { "title": "Library test", @@ -315,7 +315,7 @@ def test_error_no_metadata_section(self): # Mock parse_learning_package_toml to return a dict without 'meta' with patch( - "openedx_learning.apps.authoring.backup_restore.zipper.parse_learning_package_toml", + "openedx_learning.apps.authoring.modules.backup_restore.zipper.parse_learning_package_toml", return_value={ "learning_package": { "title": "Library test", diff --git a/tests/openedx_learning/apps/authoring/backup_restore/test_slug_hash.py b/tests/openedx_learning/apps/authoring/backup_restore/test_slug_hash.py index 292d08af1..088fcbb0f 100644 --- a/tests/openedx_learning/apps/authoring/backup_restore/test_slug_hash.py +++ b/tests/openedx_learning/apps/authoring/backup_restore/test_slug_hash.py @@ -5,7 +5,7 @@ generating slugified, hash-based filenames. """ -from openedx_learning.apps.authoring.backup_restore.zipper import slugify_hashed_filename +from openedx_learning.apps.authoring.modules.backup_restore.zipper import slugify_hashed_filename from openedx_learning.lib.test_utils import TestCase diff --git a/tests/openedx_learning/apps/authoring/components/test_api.py b/tests/openedx_learning/apps/authoring/components/test_api.py index 8a4dd44c5..8db6442f2 100644 --- a/tests/openedx_learning/apps/authoring/components/test_api.py +++ b/tests/openedx_learning/apps/authoring/components/test_api.py @@ -7,14 +7,14 @@ from django.contrib.auth.models import User as UserType # pylint: disable=imported-auth-user from django.core.exceptions import ObjectDoesNotExist -from openedx_learning.apps.authoring.collections import api as collection_api -from openedx_learning.apps.authoring.collections.models import Collection -from openedx_learning.apps.authoring.components import api as components_api -from openedx_learning.apps.authoring.components.models import Component, ComponentType -from openedx_learning.apps.authoring.contents import api as contents_api -from openedx_learning.apps.authoring.contents.models import MediaType -from openedx_learning.apps.authoring.publishing import api as publishing_api -from openedx_learning.apps.authoring.publishing.models import LearningPackage +from openedx_learning.apps.authoring.modules.collections import api as collection_api +from openedx_learning.apps.authoring.modules.collections.models import Collection +from openedx_learning.apps.authoring.modules.components import api as components_api +from openedx_learning.apps.authoring.modules.components.models import Component, ComponentType +from openedx_learning.apps.authoring.modules.contents import api as contents_api +from openedx_learning.apps.authoring.modules.contents.models import MediaType +from openedx_learning.apps.authoring.modules.publishing import api as publishing_api +from openedx_learning.apps.authoring.modules.publishing.models import LearningPackage from openedx_learning.lib.test_utils import TestCase User = get_user_model() diff --git a/tests/openedx_learning/apps/authoring/components/test_assets.py b/tests/openedx_learning/apps/authoring/components/test_assets.py index f9cbf0643..8abe8ad25 100644 --- a/tests/openedx_learning/apps/authoring/components/test_assets.py +++ b/tests/openedx_learning/apps/authoring/components/test_assets.py @@ -5,11 +5,11 @@ from pathlib import Path from uuid import uuid4 -from openedx_learning.apps.authoring.components import api as components_api -from openedx_learning.apps.authoring.components.api import AssetError -from openedx_learning.apps.authoring.contents import api as contents_api -from openedx_learning.apps.authoring.publishing import api as publishing_api -from openedx_learning.apps.authoring.publishing.models import LearningPackage +from openedx_learning.apps.authoring.modules.components import api as components_api +from openedx_learning.apps.authoring.modules.components.api import AssetError +from openedx_learning.apps.authoring.modules.contents import api as contents_api +from openedx_learning.apps.authoring.modules.publishing import api as publishing_api +from openedx_learning.apps.authoring.modules.publishing.models import LearningPackage from openedx_learning.lib.test_utils import TestCase diff --git a/tests/openedx_learning/apps/authoring/components/test_models.py b/tests/openedx_learning/apps/authoring/components/test_models.py index ca786d281..5e4ad3206 100644 --- a/tests/openedx_learning/apps/authoring/components/test_models.py +++ b/tests/openedx_learning/apps/authoring/components/test_models.py @@ -6,13 +6,13 @@ from freezegun import freeze_time -from openedx_learning.apps.authoring.components.api import ( +from openedx_learning.apps.authoring.modules.components.api import ( create_component_and_version, get_component, get_or_create_component_type, ) -from openedx_learning.apps.authoring.components.models import Component, ComponentType, ComponentVersion -from openedx_learning.apps.authoring.publishing.api import ( +from openedx_learning.apps.authoring.modules.components.models import Component, ComponentType, ComponentVersion +from openedx_learning.apps.authoring.modules.publishing.api import ( LearningPackage, create_learning_package, create_publishable_entity_version, diff --git a/tests/openedx_learning/apps/authoring/contents/test_file_storage.py b/tests/openedx_learning/apps/authoring/contents/test_file_storage.py index a94b31571..b2aa3d8b2 100644 --- a/tests/openedx_learning/apps/authoring/contents/test_file_storage.py +++ b/tests/openedx_learning/apps/authoring/contents/test_file_storage.py @@ -7,9 +7,9 @@ from django.core.exceptions import ImproperlyConfigured from django.test import override_settings -from openedx_learning.apps.authoring.contents import api as contents_api -from openedx_learning.apps.authoring.contents.models import get_storage -from openedx_learning.apps.authoring.publishing import api as publishing_api +from openedx_learning.apps.authoring.modules.contents import api as contents_api +from openedx_learning.apps.authoring.modules.contents.models import get_storage +from openedx_learning.apps.authoring.modules.publishing import api as publishing_api from openedx_learning.lib.test_utils import TestCase diff --git a/tests/openedx_learning/apps/authoring/contents/test_media_types.py b/tests/openedx_learning/apps/authoring/contents/test_media_types.py index 6f9b16b30..7cf802f3f 100644 --- a/tests/openedx_learning/apps/authoring/contents/test_media_types.py +++ b/tests/openedx_learning/apps/authoring/contents/test_media_types.py @@ -1,7 +1,7 @@ """ A few tests to make sure our MediaType lookups are working as expected. """ -from openedx_learning.apps.authoring.contents import api as contents_api +from openedx_learning.apps.authoring.modules.contents import api as contents_api from openedx_learning.lib.test_utils import TestCase diff --git a/tests/openedx_learning/apps/authoring/publishing/test_api.py b/tests/openedx_learning/apps/authoring/publishing/test_api.py index f44667178..16af541b0 100644 --- a/tests/openedx_learning/apps/authoring/publishing/test_api.py +++ b/tests/openedx_learning/apps/authoring/publishing/test_api.py @@ -10,8 +10,8 @@ from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError -from openedx_learning.apps.authoring.publishing import api as publishing_api -from openedx_learning.apps.authoring.publishing.models import ( +from openedx_learning.apps.authoring.modules.publishing import api as publishing_api +from openedx_learning.apps.authoring.modules.publishing.models import ( Container, ContainerVersion, Draft, diff --git a/tests/openedx_learning/apps/authoring/publishing/test_models.py b/tests/openedx_learning/apps/authoring/publishing/test_models.py index 60b2d0840..dec5e7cae 100644 --- a/tests/openedx_learning/apps/authoring/publishing/test_models.py +++ b/tests/openedx_learning/apps/authoring/publishing/test_models.py @@ -3,7 +3,7 @@ """ from typing import TYPE_CHECKING, assert_type -from openedx_learning.apps.authoring.publishing.models import PublishableEntityMixin, PublishableEntityVersionMixin +from openedx_learning.apps.authoring.modules.publishing.models import PublishableEntityMixin, PublishableEntityVersionMixin from openedx_learning.lib.managers import WithRelationsManager if TYPE_CHECKING: diff --git a/tests/openedx_tagging/core/tagging/test_system_defined_models.py b/tests/openedx_tagging/core/tagging/test_system_defined_models.py index f771d82ee..f4e9cfe7f 100644 --- a/tests/openedx_tagging/core/tagging/test_system_defined_models.py +++ b/tests/openedx_tagging/core/tagging/test_system_defined_models.py @@ -9,7 +9,7 @@ import pytest from django.test import TestCase, override_settings -from openedx_learning.apps.authoring.publishing.models import LearningPackage +from openedx_learning.apps.authoring.modules.publishing.models import LearningPackage from openedx_tagging.core.tagging import api from openedx_tagging.core.tagging.models import Taxonomy from openedx_tagging.core.tagging.models.system_defined import ModelSystemDefinedTaxonomy, UserSystemDefinedTaxonomy From d2bbcf56e6f314c83eaa2a5d173fc15370b01503 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Mon, 29 Dec 2025 23:31:25 -0500 Subject: [PATCH 06/13] refactor: move other authoring apps to new structure --- tests/openedx_learning/apps/authoring/collections/test_api.py | 2 +- tests/openedx_learning/apps/authoring/subsections/test_api.py | 2 +- tests/openedx_learning/apps/authoring/units/test_api.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/openedx_learning/apps/authoring/collections/test_api.py b/tests/openedx_learning/apps/authoring/collections/test_api.py index b70a8abd3..97b2f2ba4 100644 --- a/tests/openedx_learning/apps/authoring/collections/test_api.py +++ b/tests/openedx_learning/apps/authoring/collections/test_api.py @@ -17,8 +17,8 @@ ComponentType, LearningPackage, PublishableEntity, + Unit, ) -from openedx_learning.apps.authoring.units.models import Unit from openedx_learning.lib.test_utils import TestCase User = get_user_model() diff --git a/tests/openedx_learning/apps/authoring/subsections/test_api.py b/tests/openedx_learning/apps/authoring/subsections/test_api.py index 577881a9a..762176860 100644 --- a/tests/openedx_learning/apps/authoring/subsections/test_api.py +++ b/tests/openedx_learning/apps/authoring/subsections/test_api.py @@ -262,7 +262,7 @@ def test_adding_external_units(self): created_by=None, ) - @patch('openedx_learning.apps.authoring.subsections.api._pub_entities_for_units') + @patch('openedx_learning.apps.authoring.modules.subsections.api._pub_entities_for_units') def test_adding_mismatched_versions(self, mock_entities_for_units): # pylint: disable=arguments-renamed """ Test that versioned units must match their entities. diff --git a/tests/openedx_learning/apps/authoring/units/test_api.py b/tests/openedx_learning/apps/authoring/units/test_api.py index ebef4810a..21ae51993 100644 --- a/tests/openedx_learning/apps/authoring/units/test_api.py +++ b/tests/openedx_learning/apps/authoring/units/test_api.py @@ -250,7 +250,7 @@ def test_adding_external_components(self): created_by=None, ) - @patch('openedx_learning.apps.authoring.units.api._pub_entities_for_components') + @patch('openedx_learning.apps.authoring.modules.units.api._pub_entities_for_components') def test_adding_mismatched_versions(self, mock_entities_for_components): """ Test that versioned components must match their entities. From 25152d3513120c977b1f52a5cb533315a0483e81 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Tue, 30 Dec 2025 00:23:29 -0500 Subject: [PATCH 07/13] fix: make the migration work either from a new start or a teak start --- .../apps/authoring/migrations/0001_initial.py | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/openedx_learning/apps/authoring/migrations/0001_initial.py b/openedx_learning/apps/authoring/migrations/0001_initial.py index face58e64..9f009e4ae 100644 --- a/openedx_learning/apps/authoring/migrations/0001_initial.py +++ b/openedx_learning/apps/authoring/migrations/0001_initial.py @@ -5,16 +5,17 @@ (bundled with the Teak release). 2. New installs. """ +import uuid import django.core.validators import django.db.models.deletion -import openedx_learning.lib.fields -import openedx_learning.lib.validators -import uuid from django.conf import settings from django.db import migrations, models from django.db.migrations.operations.special import SeparateDatabaseAndState +from django.db.migrations.recorder import MigrationRecorder +import openedx_learning.lib.fields +import openedx_learning.lib.validators class BootstrapMigrations(SeparateDatabaseAndState): @@ -22,6 +23,38 @@ def __init__(self, operations): return super().__init__(database_operations=operations, state_operations=operations) def has_teak_release_tables(self): + """ + There are three possible outcomes: + + 1. The database we want to run this migration on already has migrations + for the smaller apps that the "authoring" is subsuming: Return True. + 2. The database has no migrations of those earlier apps: Return False. + 3. The database has *some* but not all of the migrations we expect: + Raise an error. This can happen if someone tries to upgrade and skips + the Teak release, e.g. Sumac -> Verawood directly. + """ + expected_migrations = { + "oel_collections": "0005_alter_collection_options_alter_collection_enabled", + "oel_components": "0004_remove_componentversioncontent_uuid", + "oel_contents": "0001_initial", + "oel_publishing": "0010_backfill_dependencies", + "oel_sections": "0001_initial", + "oel_subsections": "0001_initial", + "oel_units": "0001_initial", + } + if all( + MigrationRecorder.Migration.objects.filter(app=app, name=name).exists() + for app, name in expected_migrations.items() + ): + return True + + if MigrationRecorder.Migration.objects.filter(app="oel_publishing").exists(): + raise RuntimeError( + "Migration could not be run because database is in a pre-Teak " + "state. Please upgrade to Teak (openedx_learning==0.30.2) " + "before running this migration." + ) + return False def database_forwards(self, app_label, schema_editor, from_state, to_state): From 4e1e63b5be083da4d493d48aa024511d366580f4 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Tue, 30 Dec 2025 00:38:02 -0500 Subject: [PATCH 08/13] fix: fix missing renames --- .../apps/authoring/migrations/0001_initial.py | 10 ++++++ .../0002_rename_tables_to_oel_authoring.py | 32 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/openedx_learning/apps/authoring/migrations/0001_initial.py b/openedx_learning/apps/authoring/migrations/0001_initial.py index 9f009e4ae..1008fcf27 100644 --- a/openedx_learning/apps/authoring/migrations/0001_initial.py +++ b/openedx_learning/apps/authoring/migrations/0001_initial.py @@ -135,6 +135,7 @@ class Migration(migrations.Migration): options={ 'verbose_name': 'Content', 'verbose_name_plural': 'Contents', + 'db_table': 'oel_contents_content', }, ), migrations.CreateModel( @@ -171,6 +172,9 @@ class Migration(migrations.Migration): ('sub_type', openedx_learning.lib.fields.MultiCollationCharField(db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=127)), ('suffix', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=127)), ], + options={ + 'db_table': "contents_mediatype", + }, ), migrations.CreateModel( name='PublishableEntityVersionDependency', @@ -487,6 +491,7 @@ class Migration(migrations.Migration): ], options={ 'abstract': False, + 'db_table': "oel_sections_section", }, bases=('oel_authoring.container',), ), @@ -497,6 +502,7 @@ class Migration(migrations.Migration): ], options={ 'abstract': False, + 'db_table': "oel_subsections_subsection", }, bases=('oel_authoring.container',), ), @@ -507,6 +513,7 @@ class Migration(migrations.Migration): ], options={ 'abstract': False, + 'db_table': "oel_units_unit", }, bases=('oel_authoring.container',), ), @@ -556,6 +563,7 @@ class Migration(migrations.Migration): ], options={ 'abstract': False, + 'db_table': 'oel_sections_sectionversion', }, bases=('oel_authoring.containerversion',), ), @@ -566,6 +574,7 @@ class Migration(migrations.Migration): ], options={ 'abstract': False, + 'db_table': 'oel_subsections_subsectionversion', }, bases=('oel_authoring.containerversion',), ), @@ -576,6 +585,7 @@ class Migration(migrations.Migration): ], options={ 'abstract': False, + 'db_table': 'oel_units_unitversion', }, bases=('oel_authoring.containerversion',), ), diff --git a/openedx_learning/apps/authoring/migrations/0002_rename_tables_to_oel_authoring.py b/openedx_learning/apps/authoring/migrations/0002_rename_tables_to_oel_authoring.py index 41fdc31b9..17cee6d25 100644 --- a/openedx_learning/apps/authoring/migrations/0002_rename_tables_to_oel_authoring.py +++ b/openedx_learning/apps/authoring/migrations/0002_rename_tables_to_oel_authoring.py @@ -23,6 +23,10 @@ class Migration(migrations.Migration): name='collectionpublishableentity', table=None, ), + migrations.AlterModelTable( + name='content', + table=None, + ), migrations.AlterModelTable( name='component', table=None, @@ -75,6 +79,10 @@ class Migration(migrations.Migration): name='learningpackage', table=None, ), + migrations.AlterModelTable( + name='mediatype', + table=None, + ), migrations.AlterModelTable( name='publishableentity', table=None, @@ -103,4 +111,28 @@ class Migration(migrations.Migration): name='publishsideeffect', table=None, ), + migrations.AlterModelTable( + name='section', + table=None, + ), + migrations.AlterModelTable( + name='sectionversion', + table=None, + ), + migrations.AlterModelTable( + name='subsection', + table=None, + ), + migrations.AlterModelTable( + name='subsectionversion', + table=None, + ), + migrations.AlterModelTable( + name='unit', + table=None, + ), + migrations.AlterModelTable( + name='unitversion', + table=None, + ), ] From f69e1b70e5b5d08646a36d27ef51f2fc0f4eaa13 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Tue, 30 Dec 2025 00:39:57 -0500 Subject: [PATCH 09/13] fix: wrong prefix for contents media type --- openedx_learning/apps/authoring/migrations/0001_initial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openedx_learning/apps/authoring/migrations/0001_initial.py b/openedx_learning/apps/authoring/migrations/0001_initial.py index 1008fcf27..844908fd6 100644 --- a/openedx_learning/apps/authoring/migrations/0001_initial.py +++ b/openedx_learning/apps/authoring/migrations/0001_initial.py @@ -173,7 +173,7 @@ class Migration(migrations.Migration): ('suffix', openedx_learning.lib.fields.MultiCollationCharField(blank=True, db_collations={'mysql': 'utf8mb4_unicode_ci', 'sqlite': 'NOCASE'}, max_length=127)), ], options={ - 'db_table': "contents_mediatype", + 'db_table': "oel_contents_mediatype", }, ), migrations.CreateModel( From 3eb90fcb2facd09386c1bebd92b9518c9e324338 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Tue, 30 Dec 2025 01:36:49 -0500 Subject: [PATCH 10/13] refactor: move components command to authoring --- .../management/commands/add_assets_to_component.py | 0 .../apps/authoring/modules/components/management/__init__.py | 0 .../authoring/modules/components/management/commands/__init__.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename openedx_learning/apps/authoring/{modules/components => }/management/commands/add_assets_to_component.py (100%) delete mode 100644 openedx_learning/apps/authoring/modules/components/management/__init__.py delete mode 100644 openedx_learning/apps/authoring/modules/components/management/commands/__init__.py diff --git a/openedx_learning/apps/authoring/modules/components/management/commands/add_assets_to_component.py b/openedx_learning/apps/authoring/management/commands/add_assets_to_component.py similarity index 100% rename from openedx_learning/apps/authoring/modules/components/management/commands/add_assets_to_component.py rename to openedx_learning/apps/authoring/management/commands/add_assets_to_component.py diff --git a/openedx_learning/apps/authoring/modules/components/management/__init__.py b/openedx_learning/apps/authoring/modules/components/management/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/openedx_learning/apps/authoring/modules/components/management/commands/__init__.py b/openedx_learning/apps/authoring/modules/components/management/commands/__init__.py deleted file mode 100644 index e69de29bb..000000000 From 952f1a57fa6621589e19747e4f527660a5f19355 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Tue, 30 Dec 2025 23:25:52 -0500 Subject: [PATCH 11/13] refactoring: use of 'applets' convention, and some too-smart introspection --- .importlinter | 10 ++-- .../0016-python-public-api-conventions.rst | 6 +-- .../management/commands/load_components.py | 6 +-- openedx_learning/api/authoring.py | 16 +++--- openedx_learning/api/authoring_models.py | 14 ++--- openedx_learning/apps/authoring/admin.py | 20 ++++--- openedx_learning/apps/authoring/api.py | 12 +++++ .../{modules => applets}/__init__.py | 0 .../backup_restore/__init__.py | 0 .../backup_restore/admin.py | 0 .../backup_restore/api.py | 0 .../backup_restore/models.py | 0 .../backup_restore/serializers.py | 0 .../backup_restore/toml.py | 0 .../backup_restore/zipper.py | 0 .../collections/__init__.py | 0 .../{modules => applets}/collections/admin.py | 0 .../{modules => applets}/collections/api.py | 0 .../collections/models.py | 0 .../collections/readme.rst | 0 .../components/__init__.py | 0 .../{modules => applets}/components/admin.py | 0 .../{modules => applets}/components/api.py | 0 .../{modules => applets}/components/models.py | 0 .../components/readme.rst | 0 .../{modules => applets}/contents/__init__.py | 0 .../{modules => applets}/contents/admin.py | 0 .../{modules => applets}/contents/api.py | 0 .../{modules => applets}/contents/models.py | 0 .../publishing/__init__.py | 0 .../{modules => applets}/publishing/admin.py | 0 .../{modules => applets}/publishing/api.py | 0 .../publishing/contextmanagers.py | 0 .../publishing/models/__init__.py | 0 .../publishing/models/container.py | 0 .../publishing/models/draft_log.py | 0 .../publishing/models/entity_list.py | 0 .../publishing/models/learning_package.py | 0 .../publishing/models/publish_log.py | 0 .../publishing/models/publishable_entity.py | 0 .../publishing/readme.rst | 0 .../{modules => applets}/sections/__init__.py | 0 .../{modules => applets}/sections/admin.py | 0 .../{modules => applets}/sections/api.py | 0 .../{modules => applets}/sections/models.py | 0 .../subsections/__init__.py | 0 .../{modules => applets}/subsections/admin.py | 0 .../{modules => applets}/subsections/api.py | 0 .../subsections/models.py | 0 .../{modules => applets}/units/__init__.py | 0 .../{modules => applets}/units/admin.py | 0 .../{modules => applets}/units/api.py | 0 .../{modules => applets}/units/models.py | 0 openedx_learning/apps/authoring/apps.py | 16 +++--- .../authoring/management/commands/lp_dump.py | 4 +- .../authoring/management/commands/lp_load.py | 2 +- openedx_learning/apps/authoring/models.py | 20 ++++--- .../contrib/media_server/views.py | 2 +- openedx_learning/lib/appletslib.py | 54 +++++++++++++++++++ projects/dev.py | 10 ++-- .../authoring/backup_restore/test_backup.py | 2 +- .../authoring/backup_restore/test_restore.py | 14 ++--- .../backup_restore/test_slug_hash.py | 2 +- .../apps/authoring/components/test_api.py | 16 +++--- .../apps/authoring/components/test_assets.py | 10 ++-- .../apps/authoring/components/test_models.py | 6 +-- .../authoring/contents/test_file_storage.py | 6 +-- .../authoring/contents/test_media_types.py | 2 +- .../apps/authoring/publishing/test_api.py | 4 +- .../apps/authoring/publishing/test_models.py | 2 +- .../apps/authoring/subsections/test_api.py | 2 +- .../apps/authoring/units/test_api.py | 2 +- .../tagging/test_system_defined_models.py | 2 +- 73 files changed, 168 insertions(+), 94 deletions(-) create mode 100644 openedx_learning/apps/authoring/api.py rename openedx_learning/apps/authoring/{modules => applets}/__init__.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/backup_restore/__init__.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/backup_restore/admin.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/backup_restore/api.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/backup_restore/models.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/backup_restore/serializers.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/backup_restore/toml.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/backup_restore/zipper.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/collections/__init__.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/collections/admin.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/collections/api.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/collections/models.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/collections/readme.rst (100%) rename openedx_learning/apps/authoring/{modules => applets}/components/__init__.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/components/admin.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/components/api.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/components/models.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/components/readme.rst (100%) rename openedx_learning/apps/authoring/{modules => applets}/contents/__init__.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/contents/admin.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/contents/api.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/contents/models.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/__init__.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/admin.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/api.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/contextmanagers.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/models/__init__.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/models/container.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/models/draft_log.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/models/entity_list.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/models/learning_package.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/models/publish_log.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/models/publishable_entity.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/publishing/readme.rst (100%) rename openedx_learning/apps/authoring/{modules => applets}/sections/__init__.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/sections/admin.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/sections/api.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/sections/models.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/subsections/__init__.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/subsections/admin.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/subsections/api.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/subsections/models.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/units/__init__.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/units/admin.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/units/api.py (100%) rename openedx_learning/apps/authoring/{modules => applets}/units/models.py (100%) create mode 100644 openedx_learning/lib/appletslib.py diff --git a/.importlinter b/.importlinter index a6f73a545..6b14b4a31 100644 --- a/.importlinter +++ b/.importlinter @@ -36,24 +36,24 @@ layers= openedx_learning.api.authoring # The "backup_restore" app handle the new export and import mechanism. - openedx_learning.apps.authoring.modules.backup_restore + openedx_learning.apps.authoring.applets.backup_restore # The "components" app is responsible for storing versioned Components, # which is Open edX Studio terminology maps to things like individual # Problems, Videos, and blocks of HTML text. This is also the type we would # associate with a single "leaf" XBlock–one that is not a container type and # has no child elements. - openedx_learning.apps.authoring.modules.components + openedx_learning.apps.authoring.applets.components # The "contents" app stores the simplest pieces of binary and text data, # without versioning information. These belong to a single Learning Package. - openedx_learning.apps.authoring.modules.contents + openedx_learning.apps.authoring.applets.contents # The "collections" app stores arbitrary groupings of PublishableEntities. # Its only dependency should be the publishing app. - openedx_learning.apps.authoring.modules.collections + openedx_learning.apps.authoring.applets.collections # The lowest layer is "publishing", which holds the basic primitives needed # to create Learning Packages and manage the draft and publish states for # various types of content. - openedx_learning.apps.authoring.modules.publishing + openedx_learning.apps.authoring.applets.publishing diff --git a/docs/decisions/0016-python-public-api-conventions.rst b/docs/decisions/0016-python-public-api-conventions.rst index d60aa2620..23644a47d 100644 --- a/docs/decisions/0016-python-public-api-conventions.rst +++ b/docs/decisions/0016-python-public-api-conventions.rst @@ -20,7 +20,7 @@ Learning Core Django apps will be grouped into packages. Apps in ``openedx_learning`` will be grouped into broadly related packages under ``openedx_learning.apps``. The first of these groups will be "authoring" (``openedx_learning.apps.authoring``). Future packages may include "learner", "personalization", "activity", "grading", etc. Learning Core Django apps will continue to have their own ``api`` modules. - So for example, ``openedx_learning.apps.authoring.modules.components.api`` will continue to exist. + So for example, ``openedx_learning.apps.authoring.applets.components.api`` will continue to exist. Learning Core will have a top level package for its public API. All public APIs intended for use by consumers of Learning Core will be represented as modules in the ``openedx_learning.api`` package that corresponds to the app groupings (e.g. ``openedx_learning.api.authoring``). @@ -35,14 +35,14 @@ App ``api`` modules will define their public functions using ``__all__``. This relies on the individual apps to properly set ``__all__`` to the list of functions that they are willing to publicly support. App ``api`` modules within a package of apps still import from each other. - So for example, ``openedx_learning.apps.authoring.modules.components.api`` will continue to import APIs that it needs from ``..publishing.api``, instead of using the public API at ``openedx_learning.api.authoring``. These imports should not use wildcards. + So for example, ``openedx_learning.apps.authoring.applets.components.api`` will continue to import APIs that it needs from ``..publishing.api``, instead of using the public API at ``openedx_learning.api.authoring``. These imports should not use wildcards. Functions and constants that are not listed as part of a module's ``__all__`` may still be imported by other app APIs in the same package grouping. This should allow a package more flexibility to create provisional APIs that we may not want to support publicly. If a function or attribute is intended to be completely private to an app's ``api`` module (i.e. not used even by other apps in its package), it should be prefixed with an underscore. App ``api`` modules should not import directly from apps outside their package. - For example, ``openedx_learning.apps.personalization.api`` should import authoring API functions from ``openedx_learning.api.authoring``, **not** directly from something like ``openedx_learning.apps.authoring.modules.components.api``. This will help to limit the impact of refactoring app package internal changes, as well as exposing shortcomings in the existing public APIs. + For example, ``openedx_learning.apps.personalization.api`` should import authoring API functions from ``openedx_learning.api.authoring``, **not** directly from something like ``openedx_learning.apps.authoring.applets.components.api``. This will help to limit the impact of refactoring app package internal changes, as well as exposing shortcomings in the existing public APIs. Public API modules may implement their own functions. In addition to aggregating app ``api`` modules via wildcard imports, public API modules like ``openedx_learning.api.authoring`` may implement their own functionality. This will be useful for convenience functions that invoke multiple app APIs, and for backwards compatibility shims. When possible, the bulk of the logic for these should continue to live in app-defined APIs, with the public API module acting more as a glue layer. diff --git a/olx_importer/management/commands/load_components.py b/olx_importer/management/commands/load_components.py index 3ec871d4b..a52ce72db 100644 --- a/olx_importer/management/commands/load_components.py +++ b/olx_importer/management/commands/load_components.py @@ -28,9 +28,9 @@ from django.db import transaction # Model references to remove -from openedx_learning.apps.authoring.modules.components import api as components_api -from openedx_learning.apps.authoring.modules.contents import api as contents_api -from openedx_learning.apps.authoring.modules.publishing import api as publishing_api +from openedx_learning.apps.authoring.applets.components import api as components_api +from openedx_learning.apps.authoring.applets.contents import api as contents_api +from openedx_learning.apps.authoring.applets.publishing import api as publishing_api SUPPORTED_TYPES = ["problem", "video", "html"] logger = logging.getLogger(__name__) diff --git a/openedx_learning/api/authoring.py b/openedx_learning/api/authoring.py index c6799b6c1..36343f279 100644 --- a/openedx_learning/api/authoring.py +++ b/openedx_learning/api/authoring.py @@ -9,14 +9,14 @@ """ # These wildcard imports are okay because these api modules declare __all__. # pylint: disable=wildcard-import -from ..apps.authoring.modules.backup_restore.api import * -from ..apps.authoring.modules.collections.api import * -from ..apps.authoring.modules.components.api import * -from ..apps.authoring.modules.contents.api import * -from ..apps.authoring.modules.publishing.api import * -from ..apps.authoring.modules.sections.api import * -from ..apps.authoring.modules.subsections.api import * -from ..apps.authoring.modules.units.api import * +from ..apps.authoring.applets.backup_restore.api import * +from ..apps.authoring.applets.collections.api import * +from ..apps.authoring.applets.components.api import * +from ..apps.authoring.applets.contents.api import * +from ..apps.authoring.applets.publishing.api import * +from ..apps.authoring.applets.sections.api import * +from ..apps.authoring.applets.subsections.api import * +from ..apps.authoring.applets.units.api import * # This was renamed after the authoring API refactoring pushed this and other # app APIs into the openedx_learning.api.authoring module. Here I'm aliasing to diff --git a/openedx_learning/api/authoring_models.py b/openedx_learning/api/authoring_models.py index df7180cdd..cb7d3bd82 100644 --- a/openedx_learning/api/authoring_models.py +++ b/openedx_learning/api/authoring_models.py @@ -7,10 +7,10 @@ """ # These wildcard imports are okay because these modules declare __all__. # pylint: disable=wildcard-import -from ..apps.authoring.modules.collections.models import * -from ..apps.authoring.modules.components.models import * -from ..apps.authoring.modules.contents.models import * -from ..apps.authoring.modules.publishing.models import * -from ..apps.authoring.modules.sections.models import * -from ..apps.authoring.modules.subsections.models import * -from ..apps.authoring.modules.units.models import * +from ..apps.authoring.applets.collections.models import * +from ..apps.authoring.applets.components.models import * +from ..apps.authoring.applets.contents.models import * +from ..apps.authoring.applets.publishing.models import * +from ..apps.authoring.applets.sections.models import * +from ..apps.authoring.applets.subsections.models import * +from ..apps.authoring.applets.units.models import * diff --git a/openedx_learning/apps/authoring/admin.py b/openedx_learning/apps/authoring/admin.py index fc349cb3e..2c946cfb3 100644 --- a/openedx_learning/apps/authoring/admin.py +++ b/openedx_learning/apps/authoring/admin.py @@ -1,8 +1,12 @@ -from .modules.backup_restore.admin import * -from .modules.collections.admin import * -from .modules.components.admin import * -from .modules.contents.admin import * -from .modules.publishing.admin import * -from .modules.sections.admin import * -from .modules.subsections.admin import * -from .modules.units.admin import * \ No newline at end of file +from .applets.backup_restore.admin import * +from .applets.collections.admin import * +from .applets.components.admin import * +from .applets.contents.admin import * +from .applets.publishing.admin import * +from .applets.sections.admin import * +from .applets.subsections.admin import * +from .applets.units.admin import * + +#from openedx_learning.lib import appletslib + +#globals().update(appletslib.auto_import_admin()) diff --git a/openedx_learning/apps/authoring/api.py b/openedx_learning/apps/authoring/api.py new file mode 100644 index 000000000..5159b2bed --- /dev/null +++ b/openedx_learning/apps/authoring/api.py @@ -0,0 +1,12 @@ +from .applets.backup_restore.api import * +from .applets.collections.api import * +from .applets.components.api import * +from .applets.contents.api import * +from .applets.publishing.api import * +from .applets.sections.api import * +from .applets.subsections.api import * +from .applets.units.api import * + +#from openedx_learning.lib import appletslib + +#globals().update(appletslib.auto_import_api()) diff --git a/openedx_learning/apps/authoring/modules/__init__.py b/openedx_learning/apps/authoring/applets/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/modules/__init__.py rename to openedx_learning/apps/authoring/applets/__init__.py diff --git a/openedx_learning/apps/authoring/modules/backup_restore/__init__.py b/openedx_learning/apps/authoring/applets/backup_restore/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/modules/backup_restore/__init__.py rename to openedx_learning/apps/authoring/applets/backup_restore/__init__.py diff --git a/openedx_learning/apps/authoring/modules/backup_restore/admin.py b/openedx_learning/apps/authoring/applets/backup_restore/admin.py similarity index 100% rename from openedx_learning/apps/authoring/modules/backup_restore/admin.py rename to openedx_learning/apps/authoring/applets/backup_restore/admin.py diff --git a/openedx_learning/apps/authoring/modules/backup_restore/api.py b/openedx_learning/apps/authoring/applets/backup_restore/api.py similarity index 100% rename from openedx_learning/apps/authoring/modules/backup_restore/api.py rename to openedx_learning/apps/authoring/applets/backup_restore/api.py diff --git a/openedx_learning/apps/authoring/modules/backup_restore/models.py b/openedx_learning/apps/authoring/applets/backup_restore/models.py similarity index 100% rename from openedx_learning/apps/authoring/modules/backup_restore/models.py rename to openedx_learning/apps/authoring/applets/backup_restore/models.py diff --git a/openedx_learning/apps/authoring/modules/backup_restore/serializers.py b/openedx_learning/apps/authoring/applets/backup_restore/serializers.py similarity index 100% rename from openedx_learning/apps/authoring/modules/backup_restore/serializers.py rename to openedx_learning/apps/authoring/applets/backup_restore/serializers.py diff --git a/openedx_learning/apps/authoring/modules/backup_restore/toml.py b/openedx_learning/apps/authoring/applets/backup_restore/toml.py similarity index 100% rename from openedx_learning/apps/authoring/modules/backup_restore/toml.py rename to openedx_learning/apps/authoring/applets/backup_restore/toml.py diff --git a/openedx_learning/apps/authoring/modules/backup_restore/zipper.py b/openedx_learning/apps/authoring/applets/backup_restore/zipper.py similarity index 100% rename from openedx_learning/apps/authoring/modules/backup_restore/zipper.py rename to openedx_learning/apps/authoring/applets/backup_restore/zipper.py diff --git a/openedx_learning/apps/authoring/modules/collections/__init__.py b/openedx_learning/apps/authoring/applets/collections/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/modules/collections/__init__.py rename to openedx_learning/apps/authoring/applets/collections/__init__.py diff --git a/openedx_learning/apps/authoring/modules/collections/admin.py b/openedx_learning/apps/authoring/applets/collections/admin.py similarity index 100% rename from openedx_learning/apps/authoring/modules/collections/admin.py rename to openedx_learning/apps/authoring/applets/collections/admin.py diff --git a/openedx_learning/apps/authoring/modules/collections/api.py b/openedx_learning/apps/authoring/applets/collections/api.py similarity index 100% rename from openedx_learning/apps/authoring/modules/collections/api.py rename to openedx_learning/apps/authoring/applets/collections/api.py diff --git a/openedx_learning/apps/authoring/modules/collections/models.py b/openedx_learning/apps/authoring/applets/collections/models.py similarity index 100% rename from openedx_learning/apps/authoring/modules/collections/models.py rename to openedx_learning/apps/authoring/applets/collections/models.py diff --git a/openedx_learning/apps/authoring/modules/collections/readme.rst b/openedx_learning/apps/authoring/applets/collections/readme.rst similarity index 100% rename from openedx_learning/apps/authoring/modules/collections/readme.rst rename to openedx_learning/apps/authoring/applets/collections/readme.rst diff --git a/openedx_learning/apps/authoring/modules/components/__init__.py b/openedx_learning/apps/authoring/applets/components/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/modules/components/__init__.py rename to openedx_learning/apps/authoring/applets/components/__init__.py diff --git a/openedx_learning/apps/authoring/modules/components/admin.py b/openedx_learning/apps/authoring/applets/components/admin.py similarity index 100% rename from openedx_learning/apps/authoring/modules/components/admin.py rename to openedx_learning/apps/authoring/applets/components/admin.py diff --git a/openedx_learning/apps/authoring/modules/components/api.py b/openedx_learning/apps/authoring/applets/components/api.py similarity index 100% rename from openedx_learning/apps/authoring/modules/components/api.py rename to openedx_learning/apps/authoring/applets/components/api.py diff --git a/openedx_learning/apps/authoring/modules/components/models.py b/openedx_learning/apps/authoring/applets/components/models.py similarity index 100% rename from openedx_learning/apps/authoring/modules/components/models.py rename to openedx_learning/apps/authoring/applets/components/models.py diff --git a/openedx_learning/apps/authoring/modules/components/readme.rst b/openedx_learning/apps/authoring/applets/components/readme.rst similarity index 100% rename from openedx_learning/apps/authoring/modules/components/readme.rst rename to openedx_learning/apps/authoring/applets/components/readme.rst diff --git a/openedx_learning/apps/authoring/modules/contents/__init__.py b/openedx_learning/apps/authoring/applets/contents/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/modules/contents/__init__.py rename to openedx_learning/apps/authoring/applets/contents/__init__.py diff --git a/openedx_learning/apps/authoring/modules/contents/admin.py b/openedx_learning/apps/authoring/applets/contents/admin.py similarity index 100% rename from openedx_learning/apps/authoring/modules/contents/admin.py rename to openedx_learning/apps/authoring/applets/contents/admin.py diff --git a/openedx_learning/apps/authoring/modules/contents/api.py b/openedx_learning/apps/authoring/applets/contents/api.py similarity index 100% rename from openedx_learning/apps/authoring/modules/contents/api.py rename to openedx_learning/apps/authoring/applets/contents/api.py diff --git a/openedx_learning/apps/authoring/modules/contents/models.py b/openedx_learning/apps/authoring/applets/contents/models.py similarity index 100% rename from openedx_learning/apps/authoring/modules/contents/models.py rename to openedx_learning/apps/authoring/applets/contents/models.py diff --git a/openedx_learning/apps/authoring/modules/publishing/__init__.py b/openedx_learning/apps/authoring/applets/publishing/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/__init__.py rename to openedx_learning/apps/authoring/applets/publishing/__init__.py diff --git a/openedx_learning/apps/authoring/modules/publishing/admin.py b/openedx_learning/apps/authoring/applets/publishing/admin.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/admin.py rename to openedx_learning/apps/authoring/applets/publishing/admin.py diff --git a/openedx_learning/apps/authoring/modules/publishing/api.py b/openedx_learning/apps/authoring/applets/publishing/api.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/api.py rename to openedx_learning/apps/authoring/applets/publishing/api.py diff --git a/openedx_learning/apps/authoring/modules/publishing/contextmanagers.py b/openedx_learning/apps/authoring/applets/publishing/contextmanagers.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/contextmanagers.py rename to openedx_learning/apps/authoring/applets/publishing/contextmanagers.py diff --git a/openedx_learning/apps/authoring/modules/publishing/models/__init__.py b/openedx_learning/apps/authoring/applets/publishing/models/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/models/__init__.py rename to openedx_learning/apps/authoring/applets/publishing/models/__init__.py diff --git a/openedx_learning/apps/authoring/modules/publishing/models/container.py b/openedx_learning/apps/authoring/applets/publishing/models/container.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/models/container.py rename to openedx_learning/apps/authoring/applets/publishing/models/container.py diff --git a/openedx_learning/apps/authoring/modules/publishing/models/draft_log.py b/openedx_learning/apps/authoring/applets/publishing/models/draft_log.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/models/draft_log.py rename to openedx_learning/apps/authoring/applets/publishing/models/draft_log.py diff --git a/openedx_learning/apps/authoring/modules/publishing/models/entity_list.py b/openedx_learning/apps/authoring/applets/publishing/models/entity_list.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/models/entity_list.py rename to openedx_learning/apps/authoring/applets/publishing/models/entity_list.py diff --git a/openedx_learning/apps/authoring/modules/publishing/models/learning_package.py b/openedx_learning/apps/authoring/applets/publishing/models/learning_package.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/models/learning_package.py rename to openedx_learning/apps/authoring/applets/publishing/models/learning_package.py diff --git a/openedx_learning/apps/authoring/modules/publishing/models/publish_log.py b/openedx_learning/apps/authoring/applets/publishing/models/publish_log.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/models/publish_log.py rename to openedx_learning/apps/authoring/applets/publishing/models/publish_log.py diff --git a/openedx_learning/apps/authoring/modules/publishing/models/publishable_entity.py b/openedx_learning/apps/authoring/applets/publishing/models/publishable_entity.py similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/models/publishable_entity.py rename to openedx_learning/apps/authoring/applets/publishing/models/publishable_entity.py diff --git a/openedx_learning/apps/authoring/modules/publishing/readme.rst b/openedx_learning/apps/authoring/applets/publishing/readme.rst similarity index 100% rename from openedx_learning/apps/authoring/modules/publishing/readme.rst rename to openedx_learning/apps/authoring/applets/publishing/readme.rst diff --git a/openedx_learning/apps/authoring/modules/sections/__init__.py b/openedx_learning/apps/authoring/applets/sections/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/modules/sections/__init__.py rename to openedx_learning/apps/authoring/applets/sections/__init__.py diff --git a/openedx_learning/apps/authoring/modules/sections/admin.py b/openedx_learning/apps/authoring/applets/sections/admin.py similarity index 100% rename from openedx_learning/apps/authoring/modules/sections/admin.py rename to openedx_learning/apps/authoring/applets/sections/admin.py diff --git a/openedx_learning/apps/authoring/modules/sections/api.py b/openedx_learning/apps/authoring/applets/sections/api.py similarity index 100% rename from openedx_learning/apps/authoring/modules/sections/api.py rename to openedx_learning/apps/authoring/applets/sections/api.py diff --git a/openedx_learning/apps/authoring/modules/sections/models.py b/openedx_learning/apps/authoring/applets/sections/models.py similarity index 100% rename from openedx_learning/apps/authoring/modules/sections/models.py rename to openedx_learning/apps/authoring/applets/sections/models.py diff --git a/openedx_learning/apps/authoring/modules/subsections/__init__.py b/openedx_learning/apps/authoring/applets/subsections/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/modules/subsections/__init__.py rename to openedx_learning/apps/authoring/applets/subsections/__init__.py diff --git a/openedx_learning/apps/authoring/modules/subsections/admin.py b/openedx_learning/apps/authoring/applets/subsections/admin.py similarity index 100% rename from openedx_learning/apps/authoring/modules/subsections/admin.py rename to openedx_learning/apps/authoring/applets/subsections/admin.py diff --git a/openedx_learning/apps/authoring/modules/subsections/api.py b/openedx_learning/apps/authoring/applets/subsections/api.py similarity index 100% rename from openedx_learning/apps/authoring/modules/subsections/api.py rename to openedx_learning/apps/authoring/applets/subsections/api.py diff --git a/openedx_learning/apps/authoring/modules/subsections/models.py b/openedx_learning/apps/authoring/applets/subsections/models.py similarity index 100% rename from openedx_learning/apps/authoring/modules/subsections/models.py rename to openedx_learning/apps/authoring/applets/subsections/models.py diff --git a/openedx_learning/apps/authoring/modules/units/__init__.py b/openedx_learning/apps/authoring/applets/units/__init__.py similarity index 100% rename from openedx_learning/apps/authoring/modules/units/__init__.py rename to openedx_learning/apps/authoring/applets/units/__init__.py diff --git a/openedx_learning/apps/authoring/modules/units/admin.py b/openedx_learning/apps/authoring/applets/units/admin.py similarity index 100% rename from openedx_learning/apps/authoring/modules/units/admin.py rename to openedx_learning/apps/authoring/applets/units/admin.py diff --git a/openedx_learning/apps/authoring/modules/units/api.py b/openedx_learning/apps/authoring/applets/units/api.py similarity index 100% rename from openedx_learning/apps/authoring/modules/units/api.py rename to openedx_learning/apps/authoring/applets/units/api.py diff --git a/openedx_learning/apps/authoring/modules/units/models.py b/openedx_learning/apps/authoring/applets/units/models.py similarity index 100% rename from openedx_learning/apps/authoring/modules/units/models.py rename to openedx_learning/apps/authoring/applets/units/models.py diff --git a/openedx_learning/apps/authoring/apps.py b/openedx_learning/apps/authoring/apps.py index 98c544324..911851a6e 100644 --- a/openedx_learning/apps/authoring/apps.py +++ b/openedx_learning/apps/authoring/apps.py @@ -7,14 +7,14 @@ class AuthoringConfig(AppConfig): label = "oel_authoring" def ready(self): - from .modules.publishing.api import register_publishable_models - - from .modules.components.models import Component, ComponentVersion - from .modules.publishing.models import Container, ContainerVersion - from .modules.sections.models import Section, SectionVersion - from .modules.subsections.models import Subsection, SubsectionVersion - from .modules.units.models import Unit, UnitVersion - + from .api import register_publishable_models + from .models import ( + Component, ComponentVersion, + Container, ContainerVersion, + Section, SectionVersion, + Subsection, SubsectionVersion, + Unit, UnitVersion, + ) register_publishable_models(Component, ComponentVersion) register_publishable_models(Container, ContainerVersion) register_publishable_models(Section, SectionVersion) diff --git a/openedx_learning/apps/authoring/management/commands/lp_dump.py b/openedx_learning/apps/authoring/management/commands/lp_dump.py index c74f9450d..de6a158c9 100644 --- a/openedx_learning/apps/authoring/management/commands/lp_dump.py +++ b/openedx_learning/apps/authoring/management/commands/lp_dump.py @@ -8,8 +8,8 @@ from django.core.management import CommandError from django.core.management.base import BaseCommand -from openedx_learning.apps.authoring.modules.backup_restore.api import create_zip_file -from openedx_learning.apps.authoring.modules.publishing.api import LearningPackage +from openedx_learning.apps.authoring.applets.backup_restore.api import create_zip_file +from openedx_learning.apps.authoring.applets.publishing.api import LearningPackage logger = logging.getLogger(__name__) diff --git a/openedx_learning/apps/authoring/management/commands/lp_load.py b/openedx_learning/apps/authoring/management/commands/lp_load.py index cd741beb4..18084f73a 100644 --- a/openedx_learning/apps/authoring/management/commands/lp_load.py +++ b/openedx_learning/apps/authoring/management/commands/lp_load.py @@ -8,7 +8,7 @@ from django.core.management import CommandError from django.core.management.base import BaseCommand -from openedx_learning.apps.authoring.modules.backup_restore.api import load_learning_package +from openedx_learning.apps.authoring.applets.backup_restore.api import load_learning_package logger = logging.getLogger(__name__) diff --git a/openedx_learning/apps/authoring/models.py b/openedx_learning/apps/authoring/models.py index 4c729dd71..bffc8f87a 100644 --- a/openedx_learning/apps/authoring/models.py +++ b/openedx_learning/apps/authoring/models.py @@ -1,8 +1,12 @@ -from .modules.backup_restore.models import * -from .modules.collections.models import * -from .modules.components.models import * -from .modules.contents.models import * -from .modules.publishing.models import * -from .modules.sections.models import * -from .modules.subsections.models import * -from .modules.units.models import * +from .applets.backup_restore.models import * +from .applets.collections.models import * +from .applets.components.models import * +from .applets.contents.models import * +from .applets.publishing.models import * +from .applets.sections.models import * +from .applets.subsections.models import * +from .applets.units.models import * + +# from openedx_learning.lib import appletslib + +# globals().update(appletslib.auto_import_models()) diff --git a/openedx_learning/contrib/media_server/views.py b/openedx_learning/contrib/media_server/views.py index 5fdf7deb0..929867074 100644 --- a/openedx_learning/contrib/media_server/views.py +++ b/openedx_learning/contrib/media_server/views.py @@ -8,7 +8,7 @@ from django.core.exceptions import ObjectDoesNotExist from django.http import FileResponse, Http404 -from openedx_learning.apps.authoring.modules.components.api import look_up_component_version_content +from openedx_learning.apps.authoring.applets.components.api import look_up_component_version_content def component_asset( diff --git a/openedx_learning/lib/appletslib.py b/openedx_learning/lib/appletslib.py new file mode 100644 index 000000000..3cca4439f --- /dev/null +++ b/openedx_learning/lib/appletslib.py @@ -0,0 +1,54 @@ +""" +This was an attempt to make cute and clever code to dynamically discover and +import all applet modules of a certain type for aggregation purposes (e.g. the +authoring/models.py file importing from all applet models.py files). This code +actually does work, but I only realized after buildling it that it breaks +editor introspection/autocomplete, which makes the cost far too high for this +convenience. +""" + +import functools +import importlib +import inspect +import pathlib + + +def auto_import(module_name): + caller_frame_info = inspect.stack()[1] + caller_module = inspect.getmodule(caller_frame_info[0]) + caller_module_name = caller_module.__name__ + + # converts openedx_learning.authoring.models -> openedx_learning.authoring + import_base = ".".join(caller_module_name.split(".")[:-1]) + + caller_filepath = caller_frame_info.filename + caller_dir = pathlib.Path(caller_filepath).resolve().parent + applets_dir = caller_dir / "applets" + module_paths = applets_dir.rglob(f"{module_name}.py") + relative_paths = [ + module_path.relative_to(caller_dir) for module_path in module_paths + ] + all_modules_dict = {} + for relative_path in sorted(relative_paths): + module_import_name = f"{import_base}." + ".".join(relative_path.parts)[:-3] + module = importlib.import_module(module_import_name) + module_dict = vars(module) + if '__all__' in module_dict: + module_dict_to_add = { + key: module_dict[key] + for key in module_dict['__all__'] + } + else: + module_dict_to_add = { + key: val + for (key, val) in module_dict.items() + if not key.startswith('_') + } + all_modules_dict.update(module_dict_to_add) + + return all_modules_dict + + +auto_import_models = functools.partial(auto_import, "models") +auto_import_api = functools.partial(auto_import, "api") +auto_import_admin = functools.partial(auto_import, "admin") diff --git a/projects/dev.py b/projects/dev.py index 05bd2f649..b735ab0f9 100644 --- a/projects/dev.py +++ b/projects/dev.py @@ -34,14 +34,14 @@ "openedx_learning.apps.authoring", - #"openedx_learning.apps.authoring.modules.collections", - #"openedx_learning.apps.authoring.modules.components", - #"openedx_learning.apps.authoring.modules.contents", - #"openedx_learning.apps.authoring.modules.publishing", + #"openedx_learning.apps.authoring.applets.collections", + #"openedx_learning.apps.authoring.applets.components", + #"openedx_learning.apps.authoring.applets.contents", + #"openedx_learning.apps.authoring.applets.publishing", #"openedx_learning.apps.authoring.sections", #"openedx_learning.apps.authoring.subsections", #"openedx_learning.apps.authoring.units", - #"openedx_learning.apps.authoring.modules.backup_restore", + #"openedx_learning.apps.authoring.applets.backup_restore", # Learning Contrib Apps # "openedx_learning.contrib.media_server.apps.MediaServerConfig", diff --git a/tests/openedx_learning/apps/authoring/backup_restore/test_backup.py b/tests/openedx_learning/apps/authoring/backup_restore/test_backup.py index b77be9740..0a23bb4db 100644 --- a/tests/openedx_learning/apps/authoring/backup_restore/test_backup.py +++ b/tests/openedx_learning/apps/authoring/backup_restore/test_backup.py @@ -12,7 +12,7 @@ from openedx_learning.api import authoring as api from openedx_learning.api.authoring_models import Collection, Component, Content, LearningPackage, PublishableEntity -from openedx_learning.apps.authoring.modules.backup_restore.zipper import LearningPackageZipper +from openedx_learning.apps.authoring.applets.backup_restore.zipper import LearningPackageZipper from openedx_learning.lib.test_utils import TestCase User = get_user_model() diff --git a/tests/openedx_learning/apps/authoring/backup_restore/test_restore.py b/tests/openedx_learning/apps/authoring/backup_restore/test_restore.py index 287610b4f..4fa1a35c7 100644 --- a/tests/openedx_learning/apps/authoring/backup_restore/test_restore.py +++ b/tests/openedx_learning/apps/authoring/backup_restore/test_restore.py @@ -7,10 +7,10 @@ from django.contrib.auth import get_user_model from django.core.management import call_command -from openedx_learning.apps.authoring.modules.backup_restore.zipper import LearningPackageUnzipper, generate_staged_lp_key -from openedx_learning.apps.authoring.modules.collections import api as collections_api -from openedx_learning.apps.authoring.modules.components import api as components_api -from openedx_learning.apps.authoring.modules.publishing import api as publishing_api +from openedx_learning.apps.authoring.applets.backup_restore.zipper import LearningPackageUnzipper, generate_staged_lp_key +from openedx_learning.apps.authoring.applets.collections import api as collections_api +from openedx_learning.apps.authoring.applets.components import api as components_api +from openedx_learning.apps.authoring.applets.publishing import api as publishing_api from openedx_learning.lib.test_utils import TestCase from test_utils.zip_file_utils import folder_to_inmemory_zip @@ -31,7 +31,7 @@ def setUp(self): class RestoreLearningPackageCommandTest(RestoreTestCase): """Tests for the lp_load management command.""" - @patch("openedx_learning.apps.authoring.modules.backup_restore.api.load_learning_package") + @patch("openedx_learning.apps.authoring.applets.backup_restore.api.load_learning_package") def test_restore_command(self, mock_load_learning_package): # Mock load_learning_package to return our in-memory zip file restore_result = LearningPackageUnzipper(self.zip_file, user=self.user).load() @@ -284,7 +284,7 @@ def test_error_learning_package_missing_key(self): # Mock parse_learning_package_toml to return a dict without 'key' with patch( - "openedx_learning.apps.authoring.modules.backup_restore.zipper.parse_learning_package_toml", + "openedx_learning.apps.authoring.applets.backup_restore.zipper.parse_learning_package_toml", return_value={ "learning_package": { "title": "Library test", @@ -315,7 +315,7 @@ def test_error_no_metadata_section(self): # Mock parse_learning_package_toml to return a dict without 'meta' with patch( - "openedx_learning.apps.authoring.modules.backup_restore.zipper.parse_learning_package_toml", + "openedx_learning.apps.authoring.applets.backup_restore.zipper.parse_learning_package_toml", return_value={ "learning_package": { "title": "Library test", diff --git a/tests/openedx_learning/apps/authoring/backup_restore/test_slug_hash.py b/tests/openedx_learning/apps/authoring/backup_restore/test_slug_hash.py index 088fcbb0f..d1073dc81 100644 --- a/tests/openedx_learning/apps/authoring/backup_restore/test_slug_hash.py +++ b/tests/openedx_learning/apps/authoring/backup_restore/test_slug_hash.py @@ -5,7 +5,7 @@ generating slugified, hash-based filenames. """ -from openedx_learning.apps.authoring.modules.backup_restore.zipper import slugify_hashed_filename +from openedx_learning.apps.authoring.applets.backup_restore.zipper import slugify_hashed_filename from openedx_learning.lib.test_utils import TestCase diff --git a/tests/openedx_learning/apps/authoring/components/test_api.py b/tests/openedx_learning/apps/authoring/components/test_api.py index 8db6442f2..e28e34d0f 100644 --- a/tests/openedx_learning/apps/authoring/components/test_api.py +++ b/tests/openedx_learning/apps/authoring/components/test_api.py @@ -7,14 +7,14 @@ from django.contrib.auth.models import User as UserType # pylint: disable=imported-auth-user from django.core.exceptions import ObjectDoesNotExist -from openedx_learning.apps.authoring.modules.collections import api as collection_api -from openedx_learning.apps.authoring.modules.collections.models import Collection -from openedx_learning.apps.authoring.modules.components import api as components_api -from openedx_learning.apps.authoring.modules.components.models import Component, ComponentType -from openedx_learning.apps.authoring.modules.contents import api as contents_api -from openedx_learning.apps.authoring.modules.contents.models import MediaType -from openedx_learning.apps.authoring.modules.publishing import api as publishing_api -from openedx_learning.apps.authoring.modules.publishing.models import LearningPackage +from openedx_learning.apps.authoring.applets.collections import api as collection_api +from openedx_learning.apps.authoring.applets.collections.models import Collection +from openedx_learning.apps.authoring.applets.components import api as components_api +from openedx_learning.apps.authoring.applets.components.models import Component, ComponentType +from openedx_learning.apps.authoring.applets.contents import api as contents_api +from openedx_learning.apps.authoring.applets.contents.models import MediaType +from openedx_learning.apps.authoring.applets.publishing import api as publishing_api +from openedx_learning.apps.authoring.applets.publishing.models import LearningPackage from openedx_learning.lib.test_utils import TestCase User = get_user_model() diff --git a/tests/openedx_learning/apps/authoring/components/test_assets.py b/tests/openedx_learning/apps/authoring/components/test_assets.py index 8abe8ad25..d9f841d0e 100644 --- a/tests/openedx_learning/apps/authoring/components/test_assets.py +++ b/tests/openedx_learning/apps/authoring/components/test_assets.py @@ -5,11 +5,11 @@ from pathlib import Path from uuid import uuid4 -from openedx_learning.apps.authoring.modules.components import api as components_api -from openedx_learning.apps.authoring.modules.components.api import AssetError -from openedx_learning.apps.authoring.modules.contents import api as contents_api -from openedx_learning.apps.authoring.modules.publishing import api as publishing_api -from openedx_learning.apps.authoring.modules.publishing.models import LearningPackage +from openedx_learning.apps.authoring.applets.components import api as components_api +from openedx_learning.apps.authoring.applets.components.api import AssetError +from openedx_learning.apps.authoring.applets.contents import api as contents_api +from openedx_learning.apps.authoring.applets.publishing import api as publishing_api +from openedx_learning.apps.authoring.applets.publishing.models import LearningPackage from openedx_learning.lib.test_utils import TestCase diff --git a/tests/openedx_learning/apps/authoring/components/test_models.py b/tests/openedx_learning/apps/authoring/components/test_models.py index 5e4ad3206..ca6edaaa9 100644 --- a/tests/openedx_learning/apps/authoring/components/test_models.py +++ b/tests/openedx_learning/apps/authoring/components/test_models.py @@ -6,13 +6,13 @@ from freezegun import freeze_time -from openedx_learning.apps.authoring.modules.components.api import ( +from openedx_learning.apps.authoring.applets.components.api import ( create_component_and_version, get_component, get_or_create_component_type, ) -from openedx_learning.apps.authoring.modules.components.models import Component, ComponentType, ComponentVersion -from openedx_learning.apps.authoring.modules.publishing.api import ( +from openedx_learning.apps.authoring.applets.components.models import Component, ComponentType, ComponentVersion +from openedx_learning.apps.authoring.applets.publishing.api import ( LearningPackage, create_learning_package, create_publishable_entity_version, diff --git a/tests/openedx_learning/apps/authoring/contents/test_file_storage.py b/tests/openedx_learning/apps/authoring/contents/test_file_storage.py index b2aa3d8b2..47dc356da 100644 --- a/tests/openedx_learning/apps/authoring/contents/test_file_storage.py +++ b/tests/openedx_learning/apps/authoring/contents/test_file_storage.py @@ -7,9 +7,9 @@ from django.core.exceptions import ImproperlyConfigured from django.test import override_settings -from openedx_learning.apps.authoring.modules.contents import api as contents_api -from openedx_learning.apps.authoring.modules.contents.models import get_storage -from openedx_learning.apps.authoring.modules.publishing import api as publishing_api +from openedx_learning.apps.authoring.applets.contents import api as contents_api +from openedx_learning.apps.authoring.applets.contents.models import get_storage +from openedx_learning.apps.authoring.applets.publishing import api as publishing_api from openedx_learning.lib.test_utils import TestCase diff --git a/tests/openedx_learning/apps/authoring/contents/test_media_types.py b/tests/openedx_learning/apps/authoring/contents/test_media_types.py index 7cf802f3f..0216ce7bc 100644 --- a/tests/openedx_learning/apps/authoring/contents/test_media_types.py +++ b/tests/openedx_learning/apps/authoring/contents/test_media_types.py @@ -1,7 +1,7 @@ """ A few tests to make sure our MediaType lookups are working as expected. """ -from openedx_learning.apps.authoring.modules.contents import api as contents_api +from openedx_learning.apps.authoring.applets.contents import api as contents_api from openedx_learning.lib.test_utils import TestCase diff --git a/tests/openedx_learning/apps/authoring/publishing/test_api.py b/tests/openedx_learning/apps/authoring/publishing/test_api.py index 16af541b0..d204c244e 100644 --- a/tests/openedx_learning/apps/authoring/publishing/test_api.py +++ b/tests/openedx_learning/apps/authoring/publishing/test_api.py @@ -10,8 +10,8 @@ from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError -from openedx_learning.apps.authoring.modules.publishing import api as publishing_api -from openedx_learning.apps.authoring.modules.publishing.models import ( +from openedx_learning.apps.authoring.applets.publishing import api as publishing_api +from openedx_learning.apps.authoring.applets.publishing.models import ( Container, ContainerVersion, Draft, diff --git a/tests/openedx_learning/apps/authoring/publishing/test_models.py b/tests/openedx_learning/apps/authoring/publishing/test_models.py index dec5e7cae..2c1f68098 100644 --- a/tests/openedx_learning/apps/authoring/publishing/test_models.py +++ b/tests/openedx_learning/apps/authoring/publishing/test_models.py @@ -3,7 +3,7 @@ """ from typing import TYPE_CHECKING, assert_type -from openedx_learning.apps.authoring.modules.publishing.models import PublishableEntityMixin, PublishableEntityVersionMixin +from openedx_learning.apps.authoring.applets.publishing.models import PublishableEntityMixin, PublishableEntityVersionMixin from openedx_learning.lib.managers import WithRelationsManager if TYPE_CHECKING: diff --git a/tests/openedx_learning/apps/authoring/subsections/test_api.py b/tests/openedx_learning/apps/authoring/subsections/test_api.py index 762176860..6bf4fb5f9 100644 --- a/tests/openedx_learning/apps/authoring/subsections/test_api.py +++ b/tests/openedx_learning/apps/authoring/subsections/test_api.py @@ -262,7 +262,7 @@ def test_adding_external_units(self): created_by=None, ) - @patch('openedx_learning.apps.authoring.modules.subsections.api._pub_entities_for_units') + @patch('openedx_learning.apps.authoring.applets.subsections.api._pub_entities_for_units') def test_adding_mismatched_versions(self, mock_entities_for_units): # pylint: disable=arguments-renamed """ Test that versioned units must match their entities. diff --git a/tests/openedx_learning/apps/authoring/units/test_api.py b/tests/openedx_learning/apps/authoring/units/test_api.py index 21ae51993..f327e37f2 100644 --- a/tests/openedx_learning/apps/authoring/units/test_api.py +++ b/tests/openedx_learning/apps/authoring/units/test_api.py @@ -250,7 +250,7 @@ def test_adding_external_components(self): created_by=None, ) - @patch('openedx_learning.apps.authoring.modules.units.api._pub_entities_for_components') + @patch('openedx_learning.apps.authoring.applets.units.api._pub_entities_for_components') def test_adding_mismatched_versions(self, mock_entities_for_components): """ Test that versioned components must match their entities. diff --git a/tests/openedx_tagging/core/tagging/test_system_defined_models.py b/tests/openedx_tagging/core/tagging/test_system_defined_models.py index f4e9cfe7f..ccd30b336 100644 --- a/tests/openedx_tagging/core/tagging/test_system_defined_models.py +++ b/tests/openedx_tagging/core/tagging/test_system_defined_models.py @@ -9,7 +9,7 @@ import pytest from django.test import TestCase, override_settings -from openedx_learning.apps.authoring.modules.publishing.models import LearningPackage +from openedx_learning.apps.authoring.applets.publishing.models import LearningPackage from openedx_tagging.core.tagging import api from openedx_tagging.core.tagging.models import Taxonomy from openedx_tagging.core.tagging.models.system_defined import ModelSystemDefinedTaxonomy, UserSystemDefinedTaxonomy From e7470663a64ddbefe3fa8b81c49a21ed0b9d56e1 Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Wed, 31 Dec 2025 11:51:42 -0500 Subject: [PATCH 12/13] fix: add tagging back to the list of test apps --- test_settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test_settings.py b/test_settings.py index 33de37081..72bdc84e8 100644 --- a/test_settings.py +++ b/test_settings.py @@ -50,6 +50,7 @@ def root(*args): 'rules.apps.AutodiscoverRulesConfig', # Our own apps "openedx_learning.apps.authoring", + "openedx_tagging.core.tagging", ] AUTHENTICATION_BACKENDS = [ From 1ba58a2618b59350539b1dabc4fd5b74d40a972b Mon Sep 17 00:00:00 2001 From: David Ormsbee Date: Wed, 31 Dec 2025 11:55:01 -0500 Subject: [PATCH 13/13] refactor: move tests to new directory structure --- .../{backup_restore => applets}/__init__.py | 0 .../backup_restore}/__init__.py | 0 .../library_backup/collections/collection-test.toml | 0 .../library_backup/entities/section1-8ca126.toml | 0 .../library_backup/entities/subsection1-48afa3.toml | 0 .../library_backup/entities/unit1-b7eafb.toml | 0 .../4d1b2fac-8b30-42fb-872d-6b10ab580b27.toml | 0 .../component_versions/v2/block.xml | 0 .../html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2.toml | 0 .../component_versions/v2/block.xml | 0 .../html/e32d5479-9492-41f6-9222-550a7346bc37.toml | 0 .../component_versions/v4/block.xml | 0 .../component_versions/v4/static/me.png | Bin .../component_versions/v5/block.xml | 0 .../component_versions/v5/static/me.png | Bin .../1ee38208-a585-4455-a27e-4930aa541f53.toml | 0 .../component_versions/v2/block.xml | 0 .../256739e8-c2df-4ced-bd10-8156f6cfa90b.toml | 0 .../component_versions/v2/block.xml | 0 .../6681da3f-b056-4c6e-a8f9-040967907471.toml | 0 .../component_versions/v1/block.xml | 0 .../video/22601ebd-9da8-430b-9778-cfe059a98568.toml | 0 .../component_versions/v3/block.xml | 0 .../fixtures/library_backup/package.toml | 0 .../{ => applets}/backup_restore/test_backup.py | 0 .../{ => applets}/backup_restore/test_restore.py | 0 .../{ => applets}/backup_restore/test_slug_hash.py | 0 .../{components => applets/collections}/__init__.py | 0 .../authoring/{ => applets}/collections/test_api.py | 0 .../{contents => applets/components}/__init__.py | 0 .../authoring/{ => applets}/components/test_api.py | 0 .../{ => applets}/components/test_assets.py | 0 .../{ => applets}/components/test_models.py | 0 .../{publishing => applets/contents}/__init__.py | 0 .../{ => applets}/contents/test_file_storage.py | 0 .../{ => applets}/contents/test_media_types.py | 0 .../{sections => applets/publishing}/__init__.py | 0 .../authoring/{ => applets}/publishing/test_api.py | 0 .../{ => applets}/publishing/test_models.py | 0 .../{subsections => applets/sections}/__init__.py | 0 .../authoring/{ => applets}/sections/test_api.py | 0 .../{units => applets/subsections}/__init__.py | 0 .../authoring/{ => applets}/subsections/test_api.py | 0 .../apps/authoring/applets/units/__init__.py | 0 .../apps/authoring/{ => applets}/units/test_api.py | 0 45 files changed, 0 insertions(+), 0 deletions(-) rename tests/openedx_learning/apps/authoring/{backup_restore => applets}/__init__.py (100%) rename tests/openedx_learning/apps/authoring/{collections => applets/backup_restore}/__init__.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/collections/collection-test.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/section1-8ca126.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/subsection1-48afa3.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/unit1-b7eafb.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/drag-and-drop-v2/4d1b2fac-8b30-42fb-872d-6b10ab580b27.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/drag-and-drop-v2/4d1b2fac-8b30-42fb-872d-6b10ab580b27/component_versions/v2/block.xml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2/component_versions/v2/block.xml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v4/block.xml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v4/static/me.png (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v5/block.xml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v5/static/me.png (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/openassessment/1ee38208-a585-4455-a27e-4930aa541f53.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/openassessment/1ee38208-a585-4455-a27e-4930aa541f53/component_versions/v2/block.xml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/problem/256739e8-c2df-4ced-bd10-8156f6cfa90b.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/problem/256739e8-c2df-4ced-bd10-8156f6cfa90b/component_versions/v2/block.xml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/survey/6681da3f-b056-4c6e-a8f9-040967907471.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/survey/6681da3f-b056-4c6e-a8f9-040967907471/component_versions/v1/block.xml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/video/22601ebd-9da8-430b-9778-cfe059a98568.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/entities/xblock.v1/video/22601ebd-9da8-430b-9778-cfe059a98568/component_versions/v3/block.xml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/fixtures/library_backup/package.toml (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/test_backup.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/test_restore.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/backup_restore/test_slug_hash.py (100%) rename tests/openedx_learning/apps/authoring/{components => applets/collections}/__init__.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/collections/test_api.py (100%) rename tests/openedx_learning/apps/authoring/{contents => applets/components}/__init__.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/components/test_api.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/components/test_assets.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/components/test_models.py (100%) rename tests/openedx_learning/apps/authoring/{publishing => applets/contents}/__init__.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/contents/test_file_storage.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/contents/test_media_types.py (100%) rename tests/openedx_learning/apps/authoring/{sections => applets/publishing}/__init__.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/publishing/test_api.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/publishing/test_models.py (100%) rename tests/openedx_learning/apps/authoring/{subsections => applets/sections}/__init__.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/sections/test_api.py (100%) rename tests/openedx_learning/apps/authoring/{units => applets/subsections}/__init__.py (100%) rename tests/openedx_learning/apps/authoring/{ => applets}/subsections/test_api.py (100%) create mode 100644 tests/openedx_learning/apps/authoring/applets/units/__init__.py rename tests/openedx_learning/apps/authoring/{ => applets}/units/test_api.py (100%) diff --git a/tests/openedx_learning/apps/authoring/backup_restore/__init__.py b/tests/openedx_learning/apps/authoring/applets/__init__.py similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/__init__.py rename to tests/openedx_learning/apps/authoring/applets/__init__.py diff --git a/tests/openedx_learning/apps/authoring/collections/__init__.py b/tests/openedx_learning/apps/authoring/applets/backup_restore/__init__.py similarity index 100% rename from tests/openedx_learning/apps/authoring/collections/__init__.py rename to tests/openedx_learning/apps/authoring/applets/backup_restore/__init__.py diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/collections/collection-test.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/collections/collection-test.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/collections/collection-test.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/collections/collection-test.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/section1-8ca126.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/section1-8ca126.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/section1-8ca126.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/section1-8ca126.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/subsection1-48afa3.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/subsection1-48afa3.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/subsection1-48afa3.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/subsection1-48afa3.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/unit1-b7eafb.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/unit1-b7eafb.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/unit1-b7eafb.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/unit1-b7eafb.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/drag-and-drop-v2/4d1b2fac-8b30-42fb-872d-6b10ab580b27.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/drag-and-drop-v2/4d1b2fac-8b30-42fb-872d-6b10ab580b27.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/drag-and-drop-v2/4d1b2fac-8b30-42fb-872d-6b10ab580b27.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/drag-and-drop-v2/4d1b2fac-8b30-42fb-872d-6b10ab580b27.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/drag-and-drop-v2/4d1b2fac-8b30-42fb-872d-6b10ab580b27/component_versions/v2/block.xml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/drag-and-drop-v2/4d1b2fac-8b30-42fb-872d-6b10ab580b27/component_versions/v2/block.xml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/drag-and-drop-v2/4d1b2fac-8b30-42fb-872d-6b10ab580b27/component_versions/v2/block.xml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/drag-and-drop-v2/4d1b2fac-8b30-42fb-872d-6b10ab580b27/component_versions/v2/block.xml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2/component_versions/v2/block.xml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2/component_versions/v2/block.xml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2/component_versions/v2/block.xml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/c22b9f97-f1e9-4e8f-87f0-d5a3c26083e2/component_versions/v2/block.xml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v4/block.xml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v4/block.xml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v4/block.xml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v4/block.xml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v4/static/me.png b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v4/static/me.png similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v4/static/me.png rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v4/static/me.png diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v5/block.xml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v5/block.xml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v5/block.xml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v5/block.xml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v5/static/me.png b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v5/static/me.png similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v5/static/me.png rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/html/e32d5479-9492-41f6-9222-550a7346bc37/component_versions/v5/static/me.png diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/openassessment/1ee38208-a585-4455-a27e-4930aa541f53.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/openassessment/1ee38208-a585-4455-a27e-4930aa541f53.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/openassessment/1ee38208-a585-4455-a27e-4930aa541f53.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/openassessment/1ee38208-a585-4455-a27e-4930aa541f53.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/openassessment/1ee38208-a585-4455-a27e-4930aa541f53/component_versions/v2/block.xml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/openassessment/1ee38208-a585-4455-a27e-4930aa541f53/component_versions/v2/block.xml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/openassessment/1ee38208-a585-4455-a27e-4930aa541f53/component_versions/v2/block.xml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/openassessment/1ee38208-a585-4455-a27e-4930aa541f53/component_versions/v2/block.xml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/problem/256739e8-c2df-4ced-bd10-8156f6cfa90b.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/problem/256739e8-c2df-4ced-bd10-8156f6cfa90b.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/problem/256739e8-c2df-4ced-bd10-8156f6cfa90b.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/problem/256739e8-c2df-4ced-bd10-8156f6cfa90b.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/problem/256739e8-c2df-4ced-bd10-8156f6cfa90b/component_versions/v2/block.xml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/problem/256739e8-c2df-4ced-bd10-8156f6cfa90b/component_versions/v2/block.xml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/problem/256739e8-c2df-4ced-bd10-8156f6cfa90b/component_versions/v2/block.xml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/problem/256739e8-c2df-4ced-bd10-8156f6cfa90b/component_versions/v2/block.xml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/survey/6681da3f-b056-4c6e-a8f9-040967907471.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/survey/6681da3f-b056-4c6e-a8f9-040967907471.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/survey/6681da3f-b056-4c6e-a8f9-040967907471.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/survey/6681da3f-b056-4c6e-a8f9-040967907471.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/survey/6681da3f-b056-4c6e-a8f9-040967907471/component_versions/v1/block.xml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/survey/6681da3f-b056-4c6e-a8f9-040967907471/component_versions/v1/block.xml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/survey/6681da3f-b056-4c6e-a8f9-040967907471/component_versions/v1/block.xml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/survey/6681da3f-b056-4c6e-a8f9-040967907471/component_versions/v1/block.xml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/video/22601ebd-9da8-430b-9778-cfe059a98568.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/video/22601ebd-9da8-430b-9778-cfe059a98568.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/video/22601ebd-9da8-430b-9778-cfe059a98568.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/video/22601ebd-9da8-430b-9778-cfe059a98568.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/video/22601ebd-9da8-430b-9778-cfe059a98568/component_versions/v3/block.xml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/video/22601ebd-9da8-430b-9778-cfe059a98568/component_versions/v3/block.xml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/entities/xblock.v1/video/22601ebd-9da8-430b-9778-cfe059a98568/component_versions/v3/block.xml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/entities/xblock.v1/video/22601ebd-9da8-430b-9778-cfe059a98568/component_versions/v3/block.xml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/package.toml b/tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/package.toml similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/fixtures/library_backup/package.toml rename to tests/openedx_learning/apps/authoring/applets/backup_restore/fixtures/library_backup/package.toml diff --git a/tests/openedx_learning/apps/authoring/backup_restore/test_backup.py b/tests/openedx_learning/apps/authoring/applets/backup_restore/test_backup.py similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/test_backup.py rename to tests/openedx_learning/apps/authoring/applets/backup_restore/test_backup.py diff --git a/tests/openedx_learning/apps/authoring/backup_restore/test_restore.py b/tests/openedx_learning/apps/authoring/applets/backup_restore/test_restore.py similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/test_restore.py rename to tests/openedx_learning/apps/authoring/applets/backup_restore/test_restore.py diff --git a/tests/openedx_learning/apps/authoring/backup_restore/test_slug_hash.py b/tests/openedx_learning/apps/authoring/applets/backup_restore/test_slug_hash.py similarity index 100% rename from tests/openedx_learning/apps/authoring/backup_restore/test_slug_hash.py rename to tests/openedx_learning/apps/authoring/applets/backup_restore/test_slug_hash.py diff --git a/tests/openedx_learning/apps/authoring/components/__init__.py b/tests/openedx_learning/apps/authoring/applets/collections/__init__.py similarity index 100% rename from tests/openedx_learning/apps/authoring/components/__init__.py rename to tests/openedx_learning/apps/authoring/applets/collections/__init__.py diff --git a/tests/openedx_learning/apps/authoring/collections/test_api.py b/tests/openedx_learning/apps/authoring/applets/collections/test_api.py similarity index 100% rename from tests/openedx_learning/apps/authoring/collections/test_api.py rename to tests/openedx_learning/apps/authoring/applets/collections/test_api.py diff --git a/tests/openedx_learning/apps/authoring/contents/__init__.py b/tests/openedx_learning/apps/authoring/applets/components/__init__.py similarity index 100% rename from tests/openedx_learning/apps/authoring/contents/__init__.py rename to tests/openedx_learning/apps/authoring/applets/components/__init__.py diff --git a/tests/openedx_learning/apps/authoring/components/test_api.py b/tests/openedx_learning/apps/authoring/applets/components/test_api.py similarity index 100% rename from tests/openedx_learning/apps/authoring/components/test_api.py rename to tests/openedx_learning/apps/authoring/applets/components/test_api.py diff --git a/tests/openedx_learning/apps/authoring/components/test_assets.py b/tests/openedx_learning/apps/authoring/applets/components/test_assets.py similarity index 100% rename from tests/openedx_learning/apps/authoring/components/test_assets.py rename to tests/openedx_learning/apps/authoring/applets/components/test_assets.py diff --git a/tests/openedx_learning/apps/authoring/components/test_models.py b/tests/openedx_learning/apps/authoring/applets/components/test_models.py similarity index 100% rename from tests/openedx_learning/apps/authoring/components/test_models.py rename to tests/openedx_learning/apps/authoring/applets/components/test_models.py diff --git a/tests/openedx_learning/apps/authoring/publishing/__init__.py b/tests/openedx_learning/apps/authoring/applets/contents/__init__.py similarity index 100% rename from tests/openedx_learning/apps/authoring/publishing/__init__.py rename to tests/openedx_learning/apps/authoring/applets/contents/__init__.py diff --git a/tests/openedx_learning/apps/authoring/contents/test_file_storage.py b/tests/openedx_learning/apps/authoring/applets/contents/test_file_storage.py similarity index 100% rename from tests/openedx_learning/apps/authoring/contents/test_file_storage.py rename to tests/openedx_learning/apps/authoring/applets/contents/test_file_storage.py diff --git a/tests/openedx_learning/apps/authoring/contents/test_media_types.py b/tests/openedx_learning/apps/authoring/applets/contents/test_media_types.py similarity index 100% rename from tests/openedx_learning/apps/authoring/contents/test_media_types.py rename to tests/openedx_learning/apps/authoring/applets/contents/test_media_types.py diff --git a/tests/openedx_learning/apps/authoring/sections/__init__.py b/tests/openedx_learning/apps/authoring/applets/publishing/__init__.py similarity index 100% rename from tests/openedx_learning/apps/authoring/sections/__init__.py rename to tests/openedx_learning/apps/authoring/applets/publishing/__init__.py diff --git a/tests/openedx_learning/apps/authoring/publishing/test_api.py b/tests/openedx_learning/apps/authoring/applets/publishing/test_api.py similarity index 100% rename from tests/openedx_learning/apps/authoring/publishing/test_api.py rename to tests/openedx_learning/apps/authoring/applets/publishing/test_api.py diff --git a/tests/openedx_learning/apps/authoring/publishing/test_models.py b/tests/openedx_learning/apps/authoring/applets/publishing/test_models.py similarity index 100% rename from tests/openedx_learning/apps/authoring/publishing/test_models.py rename to tests/openedx_learning/apps/authoring/applets/publishing/test_models.py diff --git a/tests/openedx_learning/apps/authoring/subsections/__init__.py b/tests/openedx_learning/apps/authoring/applets/sections/__init__.py similarity index 100% rename from tests/openedx_learning/apps/authoring/subsections/__init__.py rename to tests/openedx_learning/apps/authoring/applets/sections/__init__.py diff --git a/tests/openedx_learning/apps/authoring/sections/test_api.py b/tests/openedx_learning/apps/authoring/applets/sections/test_api.py similarity index 100% rename from tests/openedx_learning/apps/authoring/sections/test_api.py rename to tests/openedx_learning/apps/authoring/applets/sections/test_api.py diff --git a/tests/openedx_learning/apps/authoring/units/__init__.py b/tests/openedx_learning/apps/authoring/applets/subsections/__init__.py similarity index 100% rename from tests/openedx_learning/apps/authoring/units/__init__.py rename to tests/openedx_learning/apps/authoring/applets/subsections/__init__.py diff --git a/tests/openedx_learning/apps/authoring/subsections/test_api.py b/tests/openedx_learning/apps/authoring/applets/subsections/test_api.py similarity index 100% rename from tests/openedx_learning/apps/authoring/subsections/test_api.py rename to tests/openedx_learning/apps/authoring/applets/subsections/test_api.py diff --git a/tests/openedx_learning/apps/authoring/applets/units/__init__.py b/tests/openedx_learning/apps/authoring/applets/units/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/openedx_learning/apps/authoring/units/test_api.py b/tests/openedx_learning/apps/authoring/applets/units/test_api.py similarity index 100% rename from tests/openedx_learning/apps/authoring/units/test_api.py rename to tests/openedx_learning/apps/authoring/applets/units/test_api.py