diff --git a/src/openedx_content/applets/sections/api.py b/src/openedx_content/applets/sections/api.py
index 17ca8781..9c547355 100644
--- a/src/openedx_content/applets/sections/api.py
+++ b/src/openedx_content/applets/sections/api.py
@@ -8,7 +8,7 @@
from typing import Iterable
from ..containers import api as containers_api
-from ..containers.models import Container, ContainerVersion
+from ..containers.models import ContainerVersion
from ..publishing.models import LearningPackage
from ..subsections.models import Subsection, SubsectionVersion
from .models import Section, SectionVersion
@@ -24,7 +24,7 @@
]
-def get_section(section_id: Container.PK, /):
+def get_section(section_id: Section.PK, /):
"""Get a section"""
return Section.objects.select_related("container").get(pk=section_id)
@@ -61,7 +61,7 @@ def create_section_and_version(
def create_next_section_version(
- section: Section | Container.PK,
+ section: Section | Section.PK,
*,
title: str | None = None,
subsections: Iterable[Subsection | SubsectionVersion] | None = None,
diff --git a/src/openedx_content/applets/sections/models.py b/src/openedx_content/applets/sections/models.py
index 3aba6a4c..78cb55a5 100644
--- a/src/openedx_content/applets/sections/models.py
+++ b/src/openedx_content/applets/sections/models.py
@@ -2,13 +2,13 @@
Models that implement sections
"""
-from typing import override
+from typing import NewType, TypeAlias, cast, override
from django.core.exceptions import ValidationError
from django.db import models
from ..containers.api import get_container_subclass_of
-from ..containers.models import Container, ContainerVersion
+from ..containers.models import Container, ContainerPK, ContainerVersion
from ..publishing.models import PublishableEntity
from ..subsections.models import Subsection
@@ -17,6 +17,8 @@
"SectionVersion",
]
+SectionPK = NewType("SectionPK", ContainerPK)
+
@Container.register_subclass
class Section(Container):
@@ -27,6 +29,8 @@ class Section(Container):
entities and can be added to other containers.
"""
+ PK: TypeAlias = SectionPK
+
type_code = "section"
olx_tag_name = "chapter" # Serializes to OLX as `...`.
@@ -37,6 +41,10 @@ class Section(Container):
primary_key=True,
)
+ @property
+ def id(self) -> SectionPK:
+ return cast(SectionPK, self.publishable_entity_id)
+
@override
@classmethod
def validate_entity(cls, entity: PublishableEntity) -> None:
diff --git a/src/openedx_content/applets/subsections/api.py b/src/openedx_content/applets/subsections/api.py
index 9ff4a08b..cc665987 100644
--- a/src/openedx_content/applets/subsections/api.py
+++ b/src/openedx_content/applets/subsections/api.py
@@ -8,7 +8,7 @@
from typing import Iterable
from ..containers import api as containers_api
-from ..containers.models import Container, ContainerVersion
+from ..containers.models import ContainerVersion
from ..publishing.models import LearningPackage
from ..units.models import Unit, UnitVersion
from .models import Subsection, SubsectionVersion
@@ -24,7 +24,7 @@
]
-def get_subsection(subsection_id: Container.PK, /):
+def get_subsection(subsection_id: Subsection.PK, /):
"""Get a subsection"""
return Subsection.objects.select_related("container").get(pk=subsection_id)
@@ -61,7 +61,7 @@ def create_subsection_and_version(
def create_next_subsection_version(
- subsection: Subsection | Container.PK,
+ subsection: Subsection | Subsection.PK,
*,
title: str | None = None,
units: Iterable[Unit | UnitVersion] | None = None,
diff --git a/src/openedx_content/applets/subsections/models.py b/src/openedx_content/applets/subsections/models.py
index ee470b6e..8484896b 100644
--- a/src/openedx_content/applets/subsections/models.py
+++ b/src/openedx_content/applets/subsections/models.py
@@ -2,13 +2,13 @@
Models that implement subsections
"""
-from typing import override
+from typing import NewType, TypeAlias, cast, override
from django.core.exceptions import ValidationError
from django.db import models
from ..containers.api import get_container_subclass_of
-from ..containers.models import Container, ContainerVersion
+from ..containers.models import Container, ContainerPK, ContainerVersion
from ..publishing.models import PublishableEntity
from ..units.models import Unit
@@ -17,6 +17,8 @@
"SubsectionVersion",
]
+SubsectionPK = NewType("SubsectionPK", ContainerPK)
+
@Container.register_subclass
class Subsection(Container):
@@ -27,6 +29,8 @@ class Subsection(Container):
entities and can be added to other containers.
"""
+ PK: TypeAlias = SubsectionPK
+
type_code = "subsection"
olx_tag_name = "sequential" # Serializes to OLX as `...`.
@@ -37,6 +41,10 @@ class Subsection(Container):
primary_key=True,
)
+ @property
+ def id(self) -> SubsectionPK:
+ return cast(SubsectionPK, self.publishable_entity_id)
+
@override
@classmethod
def validate_entity(cls, entity: PublishableEntity) -> None:
diff --git a/src/openedx_content/applets/units/api.py b/src/openedx_content/applets/units/api.py
index 7994a10f..56c040d2 100644
--- a/src/openedx_content/applets/units/api.py
+++ b/src/openedx_content/applets/units/api.py
@@ -9,7 +9,7 @@
from ..components.models import Component, ComponentVersion
from ..containers import api as containers_api
-from ..containers.models import Container, ContainerVersion
+from ..containers.models import ContainerVersion
from ..publishing.models import LearningPackage
from .models import Unit, UnitVersion
@@ -24,7 +24,7 @@
]
-def get_unit(unit_id: Container.PK, /):
+def get_unit(unit_id: Unit.PK, /):
"""Get a unit"""
return Unit.objects.select_related("container").get(pk=unit_id)
@@ -61,7 +61,7 @@ def create_unit_and_version(
def create_next_unit_version(
- unit: Unit | Container.PK,
+ unit: Unit | Unit.PK,
*,
title: str | None = None,
components: Iterable[Component | ComponentVersion] | None = None,
diff --git a/src/openedx_content/applets/units/models.py b/src/openedx_content/applets/units/models.py
index 3594acb7..a1016fd4 100644
--- a/src/openedx_content/applets/units/models.py
+++ b/src/openedx_content/applets/units/models.py
@@ -2,12 +2,12 @@
Models that implement units
"""
-from typing import override
+from typing import NewType, TypeAlias, cast, override
from django.core.exceptions import ValidationError
from django.db import models
-from ..containers.models import Container, ContainerVersion
+from ..containers.models import Container, ContainerPK, ContainerVersion
from ..publishing.models import PublishableEntity
__all__ = [
@@ -15,6 +15,8 @@
"UnitVersion",
]
+UnitPK = NewType("UnitPK", ContainerPK)
+
@Container.register_subclass
class Unit(Container):
@@ -25,6 +27,8 @@ class Unit(Container):
entities and can be added to other containers.
"""
+ PK: TypeAlias = UnitPK
+
type_code = "unit"
olx_tag_name = "vertical" # Serializes to OLX as `...`.
@@ -35,6 +39,10 @@ class Unit(Container):
primary_key=True,
)
+ @property
+ def id(self) -> UnitPK:
+ return cast(UnitPK, self.publishable_entity_id)
+
@override
@classmethod
def validate_entity(cls, entity: PublishableEntity) -> None:
diff --git a/tests/openedx_content/applets/sections/test_api.py b/tests/openedx_content/applets/sections/test_api.py
index c7024526..ba43edfd 100644
--- a/tests/openedx_content/applets/sections/test_api.py
+++ b/tests/openedx_content/applets/sections/test_api.py
@@ -8,7 +8,7 @@
from django.core.exceptions import ValidationError
import openedx_content.api as content_api
-from openedx_content.models_api import Container, Section, SectionVersion, Subsection, SubsectionVersion
+from openedx_content.models_api import Section, SectionVersion, Subsection, SubsectionVersion
from ..components.test_api import ComponentTestCase
@@ -140,14 +140,14 @@ def test_get_section(self) -> None:
def test_get_section_nonexistent(self) -> None:
"""Test `get_section()` when the subsection doesn't exist"""
- FAKE_ID = cast(Container.PK, -500)
+ FAKE_ID = cast(Section.PK, -500)
with pytest.raises(Section.DoesNotExist):
content_api.get_section(FAKE_ID)
def test_get_section_other_container_type(self) -> None:
"""Test `get_section()` when the provided PK is for a non-Subsection container"""
with pytest.raises(Section.DoesNotExist):
- content_api.get_section(self.unit_1.id)
+ content_api.get_section(self.unit_1.id) # type: ignore[arg-type]
def test_section_queries(self) -> None:
"""
diff --git a/tests/openedx_content/applets/subsections/test_api.py b/tests/openedx_content/applets/subsections/test_api.py
index 87727780..0466b3dc 100644
--- a/tests/openedx_content/applets/subsections/test_api.py
+++ b/tests/openedx_content/applets/subsections/test_api.py
@@ -1,13 +1,14 @@
"""
Basic tests for the subsections API.
"""
+
from typing import cast
import pytest
from django.core.exceptions import ValidationError
import openedx_content.api as content_api
-from openedx_content.models_api import Container, Subsection, SubsectionVersion, Unit, UnitVersion
+from openedx_content.models_api import Subsection, SubsectionVersion, Unit, UnitVersion
from ..components.test_api import ComponentTestCase
@@ -117,14 +118,14 @@ def test_get_subsection(self) -> None:
def test_get_subsection_nonexistent(self) -> None:
"""Test `get_subsection()` when the subsection doesn't exist"""
- FAKE_ID = cast(Container.PK, -500)
+ FAKE_ID = cast(Subsection.PK, -500)
with pytest.raises(Subsection.DoesNotExist):
content_api.get_subsection(FAKE_ID)
def test_get_subsection_other_container_type(self) -> None:
"""Test `get_subsection()` when the provided PK is for a non-Subsection container"""
with pytest.raises(Subsection.DoesNotExist):
- content_api.get_subsection(self.unit_1.id)
+ content_api.get_subsection(self.unit_1.id) # type: ignore[arg-type]
def test_subsection_queries(self) -> None:
"""
diff --git a/tests/openedx_content/applets/units/test_api.py b/tests/openedx_content/applets/units/test_api.py
index d21ff2a1..c5a969d7 100644
--- a/tests/openedx_content/applets/units/test_api.py
+++ b/tests/openedx_content/applets/units/test_api.py
@@ -1,13 +1,14 @@
"""
Basic tests for the units API.
"""
+
from typing import cast
import pytest
from django.core.exceptions import ValidationError
import openedx_content.api as content_api
-from openedx_content.models_api import Component, ComponentVersion, Container, Unit, UnitVersion
+from openedx_content.models_api import Component, ComponentVersion, Unit, UnitVersion
from tests.test_django_app.models import TestContainer
from ..components.test_api import ComponentTestCase
@@ -111,7 +112,7 @@ def test_get_unit(self) -> None:
def test_get_unit_nonexistent(self) -> None:
"""Test `get_unit()` when the unit doesn't exist"""
- FAKE_ID = cast(Container.PK, -500)
+ FAKE_ID = cast(Unit.PK, -500)
with pytest.raises(Unit.DoesNotExist):
content_api.get_unit(FAKE_ID)
@@ -125,7 +126,7 @@ def test_get_unit_other_container_type(self) -> None:
container_cls=TestContainer,
)
with pytest.raises(Unit.DoesNotExist):
- content_api.get_unit(other_container.id)
+ content_api.get_unit(other_container.id) # type: ignore[arg-type]
def test_unit_queries(self) -> None:
"""