Skip to content

Commit 036ee85

Browse files
refactor: validation should only ever raise ValidationError
1 parent bb7e4f7 commit 036ee85

6 files changed

Lines changed: 35 additions & 10 deletions

File tree

src/openedx_content/applets/containers/api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def _create_container_version(
263263
for entity_row in entity_list.rows:
264264
try:
265265
container_subclass.validate_entity(entity_row.entity)
266-
except Exception as exc:
266+
except ValidationError as exc:
267267
# This exception is carefully worded. The validation may have failed because the entity is of the wrong
268268
# type, but it _could_ be a of the correct type but otherwise invalid/corrupt, e.g. partially deleted.
269269
raise ValidationError(

src/openedx_content/applets/sections/models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ class Section(Container):
4242
def validate_entity(cls, entity: PublishableEntity) -> None:
4343
"""Check if the given entity is allowed as a child of a Section"""
4444
# Sections only allow Subsections as children, so the entity must be 1:1 with Container:
45-
container = entity.container # Could raise PublishableEntity.container.RelatedObjectDoesNotExist
46-
if get_container_subclass_of(container) is not Subsection:
45+
if not hasattr(entity, "container"):
46+
raise ValidationError("Only Units can be added as children of a Subsection (found non-Container child)")
47+
if get_container_subclass_of(entity.container) is not Subsection:
4748
raise ValidationError("Only Subsection can be added as children of a Section")
4849

4950

src/openedx_content/applets/subsections/models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ class Subsection(Container):
4242
def validate_entity(cls, entity: PublishableEntity) -> None:
4343
"""Check if the given entity is allowed as a child of a Subsection"""
4444
# Subsections only allow Units as children, so the entity must be 1:1 with Container:
45-
container = entity.container # Could raise PublishableEntity.container.RelatedObjectDoesNotExist
46-
if get_container_subclass_of(container) is not Unit:
45+
if not hasattr(entity, "container"):
46+
raise ValidationError("Only Units can be added as children of a Subsection (found non-Container child)")
47+
if get_container_subclass_of(entity.container) is not Unit:
4748
raise ValidationError("Only Units can be added as children of a Subsection")
4849

4950

src/openedx_content/applets/units/models.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from typing import override
66

7+
from django.core.exceptions import ValidationError
78
from django.db import models
89

910
from ..containers.models import Container, ContainerVersion
@@ -39,8 +40,8 @@ class Unit(Container):
3940
def validate_entity(cls, entity: PublishableEntity) -> None:
4041
"""Check if the given entity is allowed as a child of a Unit"""
4142
# Units only allow Components as children, so the entity must be 1:1 with Component:
42-
# This could raise PublishableEntity.component.RelatedObjectDoesNotExist
43-
getattr(entity, "component") # pylint: disable=literal-used-as-attribute
43+
if not hasattr(entity, "component"):
44+
raise ValidationError("Only Components can be added as children of a Unit")
4445

4546

4647
class UnitVersion(ContainerVersion):

tests/openedx_content/applets/subsections/test_api.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,17 +149,20 @@ def test_create_subsection_with_invalid_children(self):
149149
# Create a subsection:
150150
subsection = self.create_subsection_with_units([])
151151
subsection_version = subsection.versioning.draft
152+
152153
# Try adding a Component to a Subsection
153154
with pytest.raises(
154155
ValidationError,
155156
match='The entity "xblock.v1:problem:Query Counting" cannot be added to a "subsection" container.',
156-
):
157+
) as err:
157158
content_api.create_next_subsection_version(
158159
subsection,
159160
units=[self.component_1],
160161
created=self.now,
161162
created_by=None,
162163
)
164+
assert "(found non-Container child)" in str(err.value.__cause__)
165+
163166
# Check that a new version was not created:
164167
subsection.refresh_from_db()
165168
assert content_api.get_subsection(subsection.pk).versioning.draft == subsection_version

tests/openedx_content/applets/units/test_api.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import openedx_content.api as content_api
99
from openedx_content.models_api import Component, ComponentVersion, Unit, UnitVersion
10-
from tests.test_django_app.models import TestContainer
10+
from tests.test_django_app.models import TestContainer, TestEntity
1111

1212
from ..components.test_api import ComponentTestCase
1313

@@ -151,14 +151,33 @@ def test_create_unit_with_invalid_children(self):
151151
unit = self.create_unit_with_components([])
152152
unit_version = unit.versioning.draft
153153
unit2 = self.create_unit_with_components([], key="unit:key2", title="Unit 2")
154+
154155
# Try adding a Unit to a Unit
155-
with pytest.raises(ValidationError, match='The entity "unit:key2" cannot be added to a "unit" container.'):
156+
with pytest.raises(
157+
ValidationError, match='The entity "unit:key2" cannot be added to a "unit" container.'
158+
) as err:
156159
content_api.create_next_unit_version(
157160
unit,
158161
components=[unit2],
159162
created=self.now,
160163
created_by=None,
161164
)
165+
assert "Only Components can be added as children of a Unit" in str(err.value.__cause__)
166+
167+
# Try adding a generic entity to a Unit
168+
pe = content_api.create_publishable_entity(self.learning_package.id, "pe", created=self.now, created_by=None)
169+
pev = content_api.create_publishable_entity_version(
170+
pe.pk, version_num=1, title="t", created=self.now, created_by=None
171+
)
172+
with pytest.raises(ValidationError, match='The entity "pe" cannot be added to a "unit" container.') as err:
173+
content_api.create_next_unit_version(
174+
unit,
175+
components=[pev],
176+
created=self.now,
177+
created_by=None,
178+
)
179+
assert "Only Components can be added as children of a Unit" in str(err.value.__cause__)
180+
162181
# Check that a new version was not created:
163182
unit.refresh_from_db()
164183
assert content_api.get_unit(unit.pk).versioning.draft == unit_version

0 commit comments

Comments
 (0)