Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions openedx/core/djangoapps/content_libraries/api/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,47 @@


class ContainerType(Enum):
"""
The container types supported by content_libraries, and logic to map them to OLX.
"""
Unit = "unit"
Subsection = "subsection"
Section = "section"

@property
def olx_tag(self) -> str:
Copy link
Member Author

@kdmccormick kdmccormick Apr 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm torn between calling this block_type vs olx_tag. On one hand, we generally don't want to think of Containers as pseudo-XBlocks, so I'm trying to frame this all as an OLX thing. On the other hand, container_sync will need to understand that Unit maps to the block_type vertical.

"""
Canonical XML tag to use when representing this container as OLX.

For example, Units are encoded as <vertical>...</vertical>.

These tag names are historical. We keep them around for the backwards compatibility of OLX
and for easier interaction with legacy modulestore-powered structural XBlocks
(e.g., copy-paste of Units between courses and V2 libraries).
"""
match self:
case self.Unit:
return "vertical"
case self.Subsection:
return "sequential"
case self.Section:
return "chapter"
raise TypeError(f"unexpected ContainerType: {self!r}")

@classmethod
def from_source_olx_tag(cls, olx_tag: str) -> 'ContainerType':
"""
Get the ContainerType that this OLX tag maps to.
"""
if olx_tag == "unit":
# There is an alternative implementation to VerticalBlock called UnitBlock whose
# OLX tag is <unit>. When converting from OLX, we want to handle both <vertical>
# and <unit> as Unit containers, although the canonical serialization is still <vertical>.
return cls.Unit
try:
return next(ct for ct in cls if olx_tag == ct.olx_tag)
except StopIteration:
raise ValueError(f"no container_type for XML tag: <{olx_tag}>") from None


@dataclass(frozen=True, kw_only=True)
Expand All @@ -83,7 +123,6 @@ def from_container(cls, library_key, container: Container, associated_collection
container=container,
)
container_type = ContainerType(container_key.container_type)

published_by = ""
if last_publish_log and last_publish_log.published_by:
published_by = last_publish_log.published_by.username
Expand Down Expand Up @@ -209,7 +248,7 @@ def create_container(
created_by=user_id,
)
case _:
raise ValueError(f"Invalid container type: {container_type}")
raise NotImplementedError(f"Library support for {container_type} is in progress")

LIBRARY_CONTAINER_CREATED.send_event(
library_container=LibraryContainerData(
Expand Down
Loading