feat: Explicit mapping from container_types to OLX tags (#36580)
This is needed by several aspects of the Teak Libraries Overhaul (https://github.com/orgs/openedx/projects/66) including: * copy-paste of containers between courses and V2 libraries * syncing of containers in courses from V2 libraries * the import_from_modulestore API
This commit is contained in:
@@ -60,7 +60,47 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
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:
|
||||
"""
|
||||
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)
|
||||
@@ -83,7 +123,6 @@ class ContainerMetadata(PublishableItem):
|
||||
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
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user