Skip to content

Commit abe53ce

Browse files
authored
feat: pull entity data from PublishableEntity instances when dumping (#348)
Retrieve data from PublishableEntity and PublishableEntityVersion instances instead of relying on subclasses like Component. Introduce a get_entities function to handle entity retrieval.
1 parent 6e0472b commit abe53ce

4 files changed

Lines changed: 89 additions & 17 deletions

File tree

openedx_learning/apps/authoring/backup_restore/toml.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,8 @@
66

77
import tomlkit
88

9+
from openedx_learning.apps.authoring.publishing.models import PublishableEntity, PublishableEntityVersion
910
from openedx_learning.apps.authoring.publishing.models.learning_package import LearningPackage
10-
from openedx_learning.apps.authoring.publishing.models.publishable_entity import (
11-
PublishableEntityMixin,
12-
PublishableEntityVersionMixin,
13-
)
1411

1512

1613
def toml_learning_package(learning_package: LearningPackage) -> str:
@@ -27,29 +24,34 @@ def toml_learning_package(learning_package: LearningPackage) -> str:
2724
return tomlkit.dumps(doc)
2825

2926

30-
def toml_publishable_entity(entity: PublishableEntityMixin) -> str:
27+
def toml_publishable_entity(entity: PublishableEntity) -> str:
3128
"""Create a TOML representation of a publishable entity."""
29+
30+
current_draft_version = getattr(entity, "draft", None)
31+
current_published_version = getattr(entity, "published", None)
32+
3233
doc = tomlkit.document()
3334
entity_table = tomlkit.table()
3435
entity_table.add("uuid", str(entity.uuid))
3536
entity_table.add("can_stand_alone", entity.can_stand_alone)
3637

37-
draft = tomlkit.table()
38-
draft.add("version_num", entity.versioning.draft.version_num)
39-
entity_table.add("draft", draft)
38+
if current_draft_version:
39+
draft_table = tomlkit.table()
40+
draft_table.add("version_num", current_draft_version.version.version_num)
41+
entity_table.add("draft", draft_table)
4042

41-
published = tomlkit.table()
42-
if entity.versioning.published:
43-
published.add("version_num", entity.versioning.published.version_num)
43+
published_table = tomlkit.table()
44+
if current_published_version:
45+
published_table.add("version_num", current_published_version.version.version_num)
4446
else:
45-
published.add(tomlkit.comment("unpublished: no published_version_num"))
46-
entity_table.add("published", published)
47+
published_table.add(tomlkit.comment("unpublished: no published_version_num"))
48+
entity_table.add("published", published_table)
4749

4850
doc.add("entity", entity_table)
4951
doc.add(tomlkit.nl())
5052
doc.add(tomlkit.comment("### Versions"))
5153

52-
for entity_version in entity.versioning.versions.all():
54+
for entity_version in entity.versions.all():
5355
version = tomlkit.aot()
5456
version_table = toml_publishable_entity_version(entity_version)
5557
version.append(version_table)
@@ -58,7 +60,7 @@ def toml_publishable_entity(entity: PublishableEntityMixin) -> str:
5860
return tomlkit.dumps(doc)
5961

6062

61-
def toml_publishable_entity_version(version: PublishableEntityVersionMixin) -> tomlkit.items.Table:
63+
def toml_publishable_entity_version(version: PublishableEntityVersion) -> tomlkit.items.Table:
6264
"""Create a TOML representation of a publishable entity version."""
6365
version_table = tomlkit.table()
6466
version_table.add("title", version.title)

openedx_learning/apps/authoring/backup_restore/zipper.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pathlib import Path
77

88
from openedx_learning.apps.authoring.backup_restore.toml import toml_learning_package, toml_publishable_entity
9-
from openedx_learning.apps.authoring.components import api as components_api
9+
from openedx_learning.apps.authoring.publishing import api as publishing_api
1010
from openedx_learning.apps.authoring.publishing.models.learning_package import LearningPackage
1111

1212
TOML_PACKAGE_NAME = "package.toml"
@@ -45,7 +45,7 @@ def create_zip(self, path: str) -> None:
4545
zipf.writestr(collections_info, "") # Add explicit empty directory
4646

4747
# Add each entity's TOML file
48-
for entity in components_api.get_components(self.learning_package.pk):
48+
for entity in publishing_api.get_entities(self.learning_package.pk):
4949
# Create a TOML representation of the entity
5050
entity_toml_content: str = toml_publishable_entity(entity)
5151
entity_toml_filename = f"{entity.key}.toml"

openedx_learning/apps/authoring/publishing/api.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"get_publishable_entity_by_key",
6161
"get_last_publish",
6262
"get_all_drafts",
63+
"get_entities",
6364
"get_entities_with_unpublished_changes",
6465
"get_entities_with_unpublished_deletes",
6566
"publish_all_drafts",
@@ -261,6 +262,13 @@ def get_all_drafts(learning_package_id: int, /) -> QuerySet[Draft]:
261262
)
262263

263264

265+
def get_entities(learning_package_id: int, /) -> QuerySet[PublishableEntity]:
266+
"""
267+
Get all entities in a learning package.
268+
"""
269+
return PublishableEntity.objects.filter(learning_package_id=learning_package_id)
270+
271+
264272
def get_entities_with_unpublished_changes(
265273
learning_package_id: int,
266274
/,

tests/openedx_learning/apps/authoring/publishing/test_api.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,3 +1075,65 @@ def test_multiple_layers_of_containers(self):
10751075
assert unit_change.affected_by.first().cause == component_change
10761076
assert subsection_change.affected_by.count() == 1
10771077
assert subsection_change.affected_by.first().cause == unit_change
1078+
1079+
1080+
class EntitiesQueryTestCase(TestCase):
1081+
"""
1082+
Tests for querying PublishableEntity objects.
1083+
"""
1084+
now: datetime
1085+
learning_package_1: LearningPackage
1086+
learning_package_2: LearningPackage
1087+
1088+
@classmethod
1089+
def setUpTestData(cls) -> None:
1090+
cls.now = datetime(2025, 8, 4, 12, 00, 00, tzinfo=timezone.utc)
1091+
cls.learning_package_1 = publishing_api.create_learning_package(
1092+
"my_package_key_1",
1093+
"Entities Testing LearningPackage 🔥 1",
1094+
created=cls.now,
1095+
)
1096+
cls.learning_package_2 = publishing_api.create_learning_package(
1097+
"my_package_key_2",
1098+
"Entities Testing LearningPackage 🔥 2",
1099+
created=cls.now,
1100+
)
1101+
1102+
def test_get_entities(self) -> None:
1103+
"""
1104+
Test that get_entities returns all entities for a learning package.
1105+
"""
1106+
with publishing_api.bulk_draft_changes_for(self.learning_package_1.id):
1107+
entity = publishing_api.create_publishable_entity(
1108+
self.learning_package_1.id,
1109+
"my_entity",
1110+
created=self.now,
1111+
created_by=None,
1112+
)
1113+
publishing_api.create_publishable_entity_version(
1114+
entity.id,
1115+
version_num=1,
1116+
title="An Entity 🌴",
1117+
created=self.now,
1118+
created_by=None,
1119+
)
1120+
entity2 = publishing_api.create_publishable_entity(
1121+
self.learning_package_1.id,
1122+
"my_entity2",
1123+
created=self.now,
1124+
created_by=None,
1125+
)
1126+
publishing_api.create_publishable_entity_version(
1127+
entity2.id,
1128+
version_num=1,
1129+
title="An Entity 🌴 2",
1130+
created=self.now,
1131+
created_by=None,
1132+
)
1133+
entities = publishing_api.get_entities(self.learning_package_1.id)
1134+
assert entities.count() == 2
1135+
for entity in entities:
1136+
assert isinstance(entity, PublishableEntity)
1137+
assert entity.learning_package_id == self.learning_package_1.id
1138+
assert entity.created == self.now
1139+
assert entity.created_by is None

0 commit comments

Comments
 (0)