openedx-learning 0.19.1__tar.gz → 0.19.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. {openedx_learning-0.19.1/openedx_learning.egg-info → openedx_learning-0.19.2}/PKG-INFO +5 -4
  2. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/__init__.py +1 -1
  3. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/api.py +101 -6
  4. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/models/entity_list.py +1 -0
  5. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/units/api.py +2 -0
  6. {openedx_learning-0.19.1 → openedx_learning-0.19.2/openedx_learning.egg-info}/PKG-INFO +5 -4
  7. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/CHANGELOG.rst +0 -0
  8. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/LICENSE.txt +0 -0
  9. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/MANIFEST.in +0 -0
  10. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/README.rst +0 -0
  11. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/api/__init__.py +0 -0
  12. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/api/authoring.py +0 -0
  13. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/api/authoring_models.py +0 -0
  14. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/__init__.py +0 -0
  15. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/__init__.py +0 -0
  16. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/__init__.py +0 -0
  17. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/admin.py +0 -0
  18. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/api.py +0 -0
  19. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/apps.py +0 -0
  20. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/migrations/0001_initial.py +0 -0
  21. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/migrations/0002_remove_collection_name_collection_created_by_and_more.py +0 -0
  22. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/migrations/0003_collection_entities.py +0 -0
  23. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/migrations/0004_collection_key.py +0 -0
  24. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/migrations/0005_alter_collection_options_alter_collection_enabled.py +0 -0
  25. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/migrations/__init__.py +0 -0
  26. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/collections/models.py +0 -0
  27. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/__init__.py +0 -0
  28. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/admin.py +0 -0
  29. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/api.py +0 -0
  30. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/apps.py +0 -0
  31. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/management/__init__.py +0 -0
  32. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/management/commands/__init__.py +0 -0
  33. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/management/commands/add_assets_to_component.py +0 -0
  34. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/migrations/0001_initial.py +0 -0
  35. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/migrations/0002_alter_componentversioncontent_key.py +0 -0
  36. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/migrations/0003_remove_componentversioncontent_learner_downloadable.py +0 -0
  37. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/migrations/__init__.py +0 -0
  38. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/components/models.py +0 -0
  39. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/contents/__init__.py +0 -0
  40. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/contents/admin.py +0 -0
  41. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/contents/api.py +0 -0
  42. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/contents/apps.py +0 -0
  43. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/contents/migrations/0001_initial.py +0 -0
  44. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/contents/migrations/__init__.py +0 -0
  45. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/contents/models.py +0 -0
  46. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/__init__.py +0 -0
  47. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/admin.py +0 -0
  48. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/apps.py +0 -0
  49. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/migrations/0001_initial.py +0 -0
  50. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/migrations/0002_alter_learningpackage_key_and_more.py +0 -0
  51. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/migrations/0003_containers.py +0 -0
  52. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/migrations/0004_publishableentity_can_stand_alone.py +0 -0
  53. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/migrations/__init__.py +0 -0
  54. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/models/__init__.py +0 -0
  55. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/models/container.py +0 -0
  56. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/models/draft_published.py +0 -0
  57. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/models/learning_package.py +0 -0
  58. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/models/publish_log.py +0 -0
  59. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/publishing/models/publishable_entity.py +0 -0
  60. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/units/__init__.py +0 -0
  61. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/units/apps.py +0 -0
  62. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/units/migrations/0001_initial.py +0 -0
  63. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/units/migrations/__init__.py +0 -0
  64. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/apps/authoring/units/models.py +0 -0
  65. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/contrib/__init__.py +0 -0
  66. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/contrib/media_server/__init__.py +0 -0
  67. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/contrib/media_server/apps.py +0 -0
  68. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/contrib/media_server/urls.py +0 -0
  69. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/contrib/media_server/views.py +0 -0
  70. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/lib/__init__.py +0 -0
  71. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/lib/admin_utils.py +0 -0
  72. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/lib/cache.py +0 -0
  73. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/lib/collations.py +0 -0
  74. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/lib/fields.py +0 -0
  75. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/lib/managers.py +0 -0
  76. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/lib/test_utils.py +0 -0
  77. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/lib/validators.py +0 -0
  78. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning/py.typed +0 -0
  79. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning.egg-info/SOURCES.txt +0 -0
  80. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning.egg-info/dependency_links.txt +0 -0
  81. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning.egg-info/not-zip-safe +0 -0
  82. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning.egg-info/requires.txt +2 -2
  83. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_learning.egg-info/top_level.txt +0 -0
  84. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/__init__.py +0 -0
  85. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/__init__.py +0 -0
  86. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/__init__.py +0 -0
  87. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/admin.py +0 -0
  88. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/api.py +0 -0
  89. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/apps.py +0 -0
  90. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/data.py +0 -0
  91. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/import_export/__init__.py +0 -0
  92. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/import_export/actions.py +0 -0
  93. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/import_export/api.py +0 -0
  94. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/import_export/exceptions.py +0 -0
  95. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/import_export/import_plan.py +0 -0
  96. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/import_export/parsers.py +0 -0
  97. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/import_export/tasks.py +0 -0
  98. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/import_export/template.csv +0 -0
  99. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/import_export/template.json +0 -0
  100. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0001_initial.py +0 -0
  101. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0001_squashed.py +0 -0
  102. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0002_auto_20230718_2026.py +0 -0
  103. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0003_auto_20230721_1238.py +0 -0
  104. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0004_auto_20230723_2001.py +0 -0
  105. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0005_language_taxonomy.py +0 -0
  106. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0006_alter_objecttag_unique_together.py +0 -0
  107. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0006_auto_20230802_1631.py +0 -0
  108. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0007_tag_import_task_log_null_fix.py +0 -0
  109. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0008_taxonomy_description_not_null.py +0 -0
  110. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0009_alter_objecttag_object_id.py +0 -0
  111. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0010_cleanups.py +0 -0
  112. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0011_remove_required.py +0 -0
  113. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0012_language_taxonomy.py +0 -0
  114. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0013_tag_parent_blank.py +0 -0
  115. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0014_minor_fixes.py +0 -0
  116. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0015_taxonomy_export_id.py +0 -0
  117. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0016_object_tag_export_id.py +0 -0
  118. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0017_alter_tagimporttask_status.py +0 -0
  119. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/0018_objecttag_is_copied.py +0 -0
  120. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/migrations/__init__.py +0 -0
  121. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/models/__init__.py +0 -0
  122. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/models/base.py +0 -0
  123. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/models/import_export.py +0 -0
  124. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/models/system_defined.py +0 -0
  125. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/models/utils.py +0 -0
  126. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rest_api/__init__.py +0 -0
  127. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rest_api/paginators.py +0 -0
  128. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rest_api/urls.py +0 -0
  129. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rest_api/utils.py +0 -0
  130. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rest_api/v1/__init__.py +0 -0
  131. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rest_api/v1/permissions.py +0 -0
  132. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rest_api/v1/serializers.py +0 -0
  133. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rest_api/v1/urls.py +0 -0
  134. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rest_api/v1/views.py +0 -0
  135. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rest_api/v1/views_import.py +0 -0
  136. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/rules.py +0 -0
  137. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/core/tagging/urls.py +0 -0
  138. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/openedx_tagging/py.typed +0 -0
  139. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/requirements/base.in +0 -0
  140. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/setup.cfg +0 -0
  141. {openedx_learning-0.19.1 → openedx_learning-0.19.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: openedx-learning
3
- Version: 0.19.1
3
+ Version: 0.19.2
4
4
  Summary: Open edX Learning Core and Tagging.
5
5
  Home-page: https://github.com/openedx/openedx-learning
6
6
  Author: David Ormsbee
@@ -19,11 +19,11 @@ Classifier: Programming Language :: Python :: 3.12
19
19
  Requires-Python: >=3.11
20
20
  License-File: LICENSE.txt
21
21
  Requires-Dist: edx-drf-extensions
22
- Requires-Dist: Django<5.0
23
22
  Requires-Dist: rules<4.0
23
+ Requires-Dist: djangorestframework<4.0
24
+ Requires-Dist: Django<5.0
24
25
  Requires-Dist: celery
25
26
  Requires-Dist: attrs
26
- Requires-Dist: djangorestframework<4.0
27
27
  Dynamic: author
28
28
  Dynamic: author-email
29
29
  Dynamic: classifier
@@ -31,6 +31,7 @@ Dynamic: description
31
31
  Dynamic: home-page
32
32
  Dynamic: keywords
33
33
  Dynamic: license
34
+ Dynamic: license-file
34
35
  Dynamic: requires-dist
35
36
  Dynamic: requires-python
36
37
  Dynamic: summary
@@ -2,4 +2,4 @@
2
2
  Open edX Learning ("Learning Core").
3
3
  """
4
4
 
5
- __version__ = "0.19.1"
5
+ __version__ = "0.19.2"
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
 
9
9
  from dataclasses import dataclass
10
10
  from datetime import datetime, timezone
11
+ from enum import Enum
11
12
  from typing import TypeVar
12
13
 
13
14
  from django.core.exceptions import ObjectDoesNotExist, ValidationError
@@ -73,10 +74,12 @@ __all__ = [
73
74
  "get_container",
74
75
  "get_container_by_key",
75
76
  "get_containers",
77
+ "ChildrenEntitiesAction",
76
78
  "ContainerEntityListEntry",
77
79
  "get_entities_in_container",
78
80
  "contains_unpublished_changes",
79
81
  "get_containers_with_entity",
82
+ "get_container_children_count",
80
83
  ]
81
84
 
82
85
 
@@ -771,6 +774,70 @@ def create_container_version(
771
774
  return container_version
772
775
 
773
776
 
777
+ class ChildrenEntitiesAction(Enum):
778
+ """Possible actions for children entities"""
779
+
780
+ APPEND = "append"
781
+ REMOVE = "remove"
782
+ REPLACE = "replace"
783
+
784
+
785
+ def create_next_entity_list(
786
+ learning_package_id: int,
787
+ last_version: ContainerVersion,
788
+ publishable_entities_pks: list[int],
789
+ entity_version_pks: list[int | None] | None,
790
+ entities_action: ChildrenEntitiesAction = ChildrenEntitiesAction.REPLACE,
791
+ ) -> EntityList:
792
+ """
793
+ Creates next entity list based on the given entities_action.
794
+
795
+ Args:
796
+ learning_package_id: Learning package ID
797
+ last_version: Last version of container.
798
+ publishable_entities_pks: The IDs of the members current members of the container.
799
+ entity_version_pks: The IDs of the versions to pin to, if pinning is desired.
800
+ entities_action: APPEND, REMOVE or REPLACE given entities from/to the container
801
+
802
+ Returns:
803
+ The newly created entity list.
804
+ """
805
+ if entity_version_pks is None:
806
+ entity_version_pks: list[int | None] = [None] * len(publishable_entities_pks) # type: ignore[no-redef]
807
+ if entities_action == ChildrenEntitiesAction.APPEND:
808
+ # get previous entity list rows
809
+ last_entities = last_version.entity_list.entitylistrow_set.only(
810
+ "entity_id",
811
+ "entity_version_id"
812
+ ).order_by("order_num")
813
+ # append given publishable_entities_pks and entity_version_pks
814
+ publishable_entities_pks = [entity.entity_id for entity in last_entities] + publishable_entities_pks
815
+ entity_version_pks = [ # type: ignore[operator, assignment]
816
+ entity.entity_version_id
817
+ for entity in last_entities
818
+ ] + entity_version_pks
819
+ elif entities_action == ChildrenEntitiesAction.REMOVE:
820
+ # get previous entity list rows
821
+ last_entities = last_version.entity_list.entitylistrow_set.only(
822
+ "entity_id",
823
+ "entity_version_id"
824
+ ).order_by("order_num")
825
+ # Remove entities that are in publishable_entities_pks
826
+ new_entities = [
827
+ entity
828
+ for entity in last_entities
829
+ if entity.entity_id not in publishable_entities_pks
830
+ ]
831
+ publishable_entities_pks = [entity.entity_id for entity in new_entities]
832
+ entity_version_pks = [entity.entity_version_id for entity in new_entities]
833
+ next_entity_list = create_entity_list_with_rows(
834
+ entity_pks=publishable_entities_pks,
835
+ entity_version_pks=entity_version_pks, # type: ignore[arg-type]
836
+ learning_package_id=learning_package_id,
837
+ )
838
+ return next_entity_list
839
+
840
+
774
841
  def create_next_container_version(
775
842
  container_pk: int,
776
843
  *,
@@ -780,6 +847,7 @@ def create_next_container_version(
780
847
  created: datetime,
781
848
  created_by: int | None,
782
849
  container_version_cls: type[ContainerVersionModel] = ContainerVersion, # type: ignore[assignment]
850
+ entities_action: ChildrenEntitiesAction = ChildrenEntitiesAction.REPLACE,
783
851
  ) -> ContainerVersionModel:
784
852
  """
785
853
  [ 🛑 UNSTABLE ]
@@ -815,13 +883,14 @@ def create_next_container_version(
815
883
  # We're only changing metadata. Keep the same entity list.
816
884
  next_entity_list = last_version.entity_list
817
885
  else:
818
- if entity_version_pks is None:
819
- entity_version_pks = [None] * len(publishable_entities_pks)
820
- next_entity_list = create_entity_list_with_rows(
821
- entity_pks=publishable_entities_pks,
822
- entity_version_pks=entity_version_pks,
823
- learning_package_id=entity.learning_package_id,
886
+ next_entity_list = create_next_entity_list(
887
+ entity.learning_package_id,
888
+ last_version,
889
+ publishable_entities_pks,
890
+ entity_version_pks,
891
+ entities_action
824
892
  )
893
+
825
894
  next_container_version = _create_container_version(
826
895
  container,
827
896
  next_version_num,
@@ -1018,3 +1087,29 @@ def get_containers_with_entity(
1018
1087
  # publishable_entity__draft__version__containerversion__entity_list__in=lists
1019
1088
  # )
1020
1089
  return qs
1090
+
1091
+
1092
+ def get_container_children_count(
1093
+ container: Container,
1094
+ *,
1095
+ published: bool,
1096
+ ):
1097
+ """
1098
+ [ 🛑 UNSTABLE ]
1099
+ Get the count of entities in the current draft or published version of the given container.
1100
+
1101
+ Args:
1102
+ container: The Container, e.g. returned by `get_container()`
1103
+ published: `True` if we want the published version of the container, or
1104
+ `False` for the draft version.
1105
+ """
1106
+ assert isinstance(container, Container)
1107
+ container_version = container.versioning.published if published else container.versioning.draft
1108
+ if container_version is None:
1109
+ raise ContainerVersion.DoesNotExist # This container has not been published yet, or has been deleted.
1110
+ assert isinstance(container_version, ContainerVersion)
1111
+ if published:
1112
+ filter_deleted = {"entity__published__version__isnull": False}
1113
+ else:
1114
+ filter_deleted = {"entity__draft__version__isnull": False}
1115
+ return container_version.entity_list.entitylistrow_set.filter(**filter_deleted).count()
@@ -60,6 +60,7 @@ class EntityListRow(models.Model):
60
60
  )
61
61
 
62
62
  class Meta:
63
+ ordering = ["order_num"]
63
64
  constraints = [
64
65
  # If (entity_list, order_num) is not unique, it likely indicates a race condition - so force uniqueness.
65
66
  models.UniqueConstraint(
@@ -130,6 +130,7 @@ def create_next_unit_version(
130
130
  components: list[Component | ComponentVersion] | None = None,
131
131
  created: datetime,
132
132
  created_by: int | None = None,
133
+ entities_action: publishing_api.ChildrenEntitiesAction = publishing_api.ChildrenEntitiesAction.REPLACE,
133
134
  ) -> UnitVersion:
134
135
  """
135
136
  [ 🛑 UNSTABLE ] Create the next unit version.
@@ -151,6 +152,7 @@ def create_next_unit_version(
151
152
  created=created,
152
153
  created_by=created_by,
153
154
  container_version_cls=UnitVersion,
155
+ entities_action=entities_action,
154
156
  )
155
157
  return unit_version
156
158
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: openedx-learning
3
- Version: 0.19.1
3
+ Version: 0.19.2
4
4
  Summary: Open edX Learning Core and Tagging.
5
5
  Home-page: https://github.com/openedx/openedx-learning
6
6
  Author: David Ormsbee
@@ -19,11 +19,11 @@ Classifier: Programming Language :: Python :: 3.12
19
19
  Requires-Python: >=3.11
20
20
  License-File: LICENSE.txt
21
21
  Requires-Dist: edx-drf-extensions
22
- Requires-Dist: Django<5.0
23
22
  Requires-Dist: rules<4.0
23
+ Requires-Dist: djangorestframework<4.0
24
+ Requires-Dist: Django<5.0
24
25
  Requires-Dist: celery
25
26
  Requires-Dist: attrs
26
- Requires-Dist: djangorestframework<4.0
27
27
  Dynamic: author
28
28
  Dynamic: author-email
29
29
  Dynamic: classifier
@@ -31,6 +31,7 @@ Dynamic: description
31
31
  Dynamic: home-page
32
32
  Dynamic: keywords
33
33
  Dynamic: license
34
+ Dynamic: license-file
34
35
  Dynamic: requires-dist
35
36
  Dynamic: requires-python
36
37
  Dynamic: summary
@@ -1,6 +1,6 @@
1
1
  edx-drf-extensions
2
- Django<5.0
3
2
  rules<4.0
3
+ djangorestframework<4.0
4
+ Django<5.0
4
5
  celery
5
6
  attrs
6
- djangorestframework<4.0