openedx-learning 0.16.1__tar.gz → 0.16.3__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.
- {openedx_learning-0.16.1/openedx_learning.egg-info → openedx_learning-0.16.3}/PKG-INFO +5 -5
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/__init__.py +1 -1
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/api.py +26 -6
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/management/commands/add_assets_to_component.py +3 -27
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/contents/models.py +8 -2
- {openedx_learning-0.16.1 → openedx_learning-0.16.3/openedx_learning.egg-info}/PKG-INFO +5 -5
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/CHANGELOG.rst +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/LICENSE.txt +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/MANIFEST.in +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/README.rst +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/api/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/api/authoring.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/api/authoring_models.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/admin.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/api.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/apps.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/migrations/0001_initial.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/migrations/0002_remove_collection_name_collection_created_by_and_more.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/migrations/0003_collection_entities.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/migrations/0004_collection_key.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/migrations/0005_alter_collection_options_alter_collection_enabled.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/migrations/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/collections/models.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/admin.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/apps.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/management/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/management/commands/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/migrations/0001_initial.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/migrations/0002_alter_componentversioncontent_key.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/migrations/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/components/models.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/contents/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/contents/admin.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/contents/api.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/contents/apps.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/contents/migrations/0001_initial.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/contents/migrations/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/publishing/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/publishing/admin.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/publishing/api.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/publishing/apps.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/publishing/migrations/0001_initial.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/publishing/migrations/0002_alter_learningpackage_key_and_more.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/publishing/migrations/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/publishing/model_mixins.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/publishing/models.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/contrib/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/contrib/media_server/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/contrib/media_server/apps.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/contrib/media_server/urls.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/contrib/media_server/views.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/lib/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/lib/admin_utils.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/lib/cache.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/lib/collations.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/lib/fields.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/lib/managers.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/lib/test_utils.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/lib/validators.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/py.typed +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning.egg-info/SOURCES.txt +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning.egg-info/dependency_links.txt +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning.egg-info/not-zip-safe +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning.egg-info/requires.txt +4 -4
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning.egg-info/top_level.txt +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/admin.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/api.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/apps.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/data.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/import_export/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/import_export/actions.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/import_export/api.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/import_export/exceptions.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/import_export/import_plan.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/import_export/parsers.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/import_export/tasks.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/import_export/template.csv +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/import_export/template.json +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0001_initial.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0001_squashed.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0002_auto_20230718_2026.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0003_auto_20230721_1238.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0004_auto_20230723_2001.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0005_language_taxonomy.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0006_alter_objecttag_unique_together.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0006_auto_20230802_1631.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0007_tag_import_task_log_null_fix.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0008_taxonomy_description_not_null.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0009_alter_objecttag_object_id.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0010_cleanups.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0011_remove_required.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0012_language_taxonomy.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0013_tag_parent_blank.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0014_minor_fixes.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0015_taxonomy_export_id.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0016_object_tag_export_id.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0017_alter_tagimporttask_status.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/0018_objecttag_is_copied.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/migrations/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/models/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/models/base.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/models/import_export.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/models/system_defined.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/models/utils.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/paginators.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/urls.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/utils.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/v1/__init__.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/v1/permissions.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/v1/serializers.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/v1/urls.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/v1/views.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/v1/views_import.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rules.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/urls.py +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/py.typed +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/requirements/base.in +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/setup.cfg +0 -0
- {openedx_learning-0.16.1 → openedx_learning-0.16.3}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: openedx-learning
|
|
3
|
-
Version: 0.16.
|
|
3
|
+
Version: 0.16.3
|
|
4
4
|
Summary: Open edX Learning Core and Tagging.
|
|
5
5
|
Home-page: https://github.com/openedx/openedx-learning
|
|
6
6
|
Author: David Ormsbee
|
|
@@ -18,12 +18,12 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Requires-Python: >=3.11
|
|
20
20
|
License-File: LICENSE.txt
|
|
21
|
-
Requires-Dist: attrs
|
|
22
|
-
Requires-Dist: celery
|
|
23
|
-
Requires-Dist: rules<4.0
|
|
24
|
-
Requires-Dist: Django<5.0
|
|
25
21
|
Requires-Dist: edx-drf-extensions
|
|
22
|
+
Requires-Dist: Django<5.0
|
|
23
|
+
Requires-Dist: celery
|
|
26
24
|
Requires-Dist: djangorestframework<4.0
|
|
25
|
+
Requires-Dist: attrs
|
|
26
|
+
Requires-Dist: rules<4.0
|
|
27
27
|
|
|
28
28
|
Open edX Learning Core (and Tagging)
|
|
29
29
|
====================================
|
|
@@ -12,6 +12,7 @@ are stored in this app.
|
|
|
12
12
|
"""
|
|
13
13
|
from __future__ import annotations
|
|
14
14
|
|
|
15
|
+
import mimetypes
|
|
15
16
|
from datetime import datetime, timezone
|
|
16
17
|
from enum import StrEnum, auto
|
|
17
18
|
from logging import getLogger
|
|
@@ -129,7 +130,7 @@ def create_component_version(
|
|
|
129
130
|
def create_next_component_version(
|
|
130
131
|
component_pk: int,
|
|
131
132
|
/,
|
|
132
|
-
content_to_replace: dict[str, int | None],
|
|
133
|
+
content_to_replace: dict[str, int | None | bytes],
|
|
133
134
|
created: datetime,
|
|
134
135
|
title: str | None = None,
|
|
135
136
|
created_by: int | None = None,
|
|
@@ -140,11 +141,14 @@ def create_next_component_version(
|
|
|
140
141
|
A very common pattern for making a new ComponentVersion is going to be "make
|
|
141
142
|
it just like the last version, except changing these one or two things".
|
|
142
143
|
Before calling this, you should create any new contents via the contents
|
|
143
|
-
API
|
|
144
|
+
API or send the content bytes as part of ``content_to_replace`` values.
|
|
144
145
|
|
|
145
146
|
The ``content_to_replace`` dict is a mapping of strings representing the
|
|
146
|
-
local path/key for a file, to ``Content.id`` values. Using
|
|
147
|
-
a value in this dict means to delete that key in the next version.
|
|
147
|
+
local path/key for a file, to ``Content.id`` or content bytes values. Using
|
|
148
|
+
`None` for a value in this dict means to delete that key in the next version.
|
|
149
|
+
|
|
150
|
+
Make sure to wrap the function call on a atomic statement:
|
|
151
|
+
``with transaction.atomic():``
|
|
148
152
|
|
|
149
153
|
It is okay to mark entries for deletion that don't exist. For instance, if a
|
|
150
154
|
version has ``a.txt`` and ``b.txt``, sending a ``content_to_replace`` value
|
|
@@ -186,11 +190,27 @@ def create_next_component_version(
|
|
|
186
190
|
component_id=component_pk,
|
|
187
191
|
)
|
|
188
192
|
# First copy the new stuff over...
|
|
189
|
-
for key,
|
|
193
|
+
for key, content_pk_or_bytes in content_to_replace.items():
|
|
190
194
|
# If the content_pk is None, it means we want to remove the
|
|
191
195
|
# content represented by our key from the next version. Otherwise,
|
|
192
196
|
# we add our key->content_pk mapping to the next version.
|
|
193
|
-
if
|
|
197
|
+
if content_pk_or_bytes is not None:
|
|
198
|
+
if isinstance(content_pk_or_bytes, bytes):
|
|
199
|
+
file_path, file_content = key, content_pk_or_bytes
|
|
200
|
+
media_type_str, _encoding = mimetypes.guess_type(file_path)
|
|
201
|
+
# We use "application/octet-stream" as a generic fallback media type, per
|
|
202
|
+
# RFC 2046: https://datatracker.ietf.org/doc/html/rfc2046
|
|
203
|
+
media_type_str = media_type_str or "application/octet-stream"
|
|
204
|
+
media_type = contents_api.get_or_create_media_type(media_type_str)
|
|
205
|
+
content = contents_api.get_or_create_file_content(
|
|
206
|
+
component.learning_package.id,
|
|
207
|
+
media_type.id,
|
|
208
|
+
data=file_content,
|
|
209
|
+
created=created,
|
|
210
|
+
)
|
|
211
|
+
content_pk = content.pk
|
|
212
|
+
else:
|
|
213
|
+
content_pk = content_pk_or_bytes
|
|
194
214
|
ComponentVersionContent.objects.create(
|
|
195
215
|
content_id=content_pk,
|
|
196
216
|
component_version=component_version,
|
|
@@ -4,14 +4,11 @@ Management command to add files to a Component.
|
|
|
4
4
|
This is mostly meant to be a debugging tool to let us to easily load some test
|
|
5
5
|
asset data into the system.
|
|
6
6
|
"""
|
|
7
|
-
import mimetypes
|
|
8
7
|
import pathlib
|
|
9
8
|
from datetime import datetime, timezone
|
|
10
9
|
|
|
11
10
|
from django.core.management.base import BaseCommand
|
|
12
11
|
|
|
13
|
-
from ....components.api import create_component_version_content
|
|
14
|
-
from ....contents.api import get_or_create_file_content, get_or_create_media_type
|
|
15
12
|
from ....publishing.api import get_learning_package_by_key
|
|
16
13
|
from ...api import create_next_component_version, get_component_by_key
|
|
17
14
|
|
|
@@ -69,39 +66,18 @@ class Command(BaseCommand):
|
|
|
69
66
|
)
|
|
70
67
|
|
|
71
68
|
created = datetime.now(tz=timezone.utc)
|
|
72
|
-
|
|
73
|
-
local_keys_to_content = {}
|
|
69
|
+
local_keys_to_content_bytes = {}
|
|
74
70
|
|
|
75
71
|
for file_mapping in file_mappings:
|
|
76
72
|
local_key, file_path = file_mapping.split(":", 1)
|
|
77
73
|
|
|
78
|
-
|
|
79
|
-
if not file_path:
|
|
80
|
-
keys_to_remove.add(local_key)
|
|
81
|
-
continue
|
|
82
|
-
|
|
83
|
-
media_type_str, _encoding = mimetypes.guess_type(file_path)
|
|
84
|
-
media_type = get_or_create_media_type(media_type_str)
|
|
85
|
-
content = get_or_create_file_content(
|
|
86
|
-
learning_package.id,
|
|
87
|
-
media_type.id,
|
|
88
|
-
data=pathlib.Path(file_path).read_bytes(),
|
|
89
|
-
created=created,
|
|
90
|
-
)
|
|
91
|
-
local_keys_to_content[local_key] = content.id
|
|
74
|
+
local_keys_to_content_bytes[local_key] = pathlib.Path(file_path).read_bytes() if file_path else None
|
|
92
75
|
|
|
93
76
|
next_version = create_next_component_version(
|
|
94
77
|
component.pk,
|
|
95
|
-
content_to_replace=
|
|
78
|
+
content_to_replace=local_keys_to_content_bytes,
|
|
96
79
|
created=created,
|
|
97
80
|
)
|
|
98
|
-
for local_key, content_id in sorted(local_keys_to_content.items()):
|
|
99
|
-
create_component_version_content(
|
|
100
|
-
next_version.pk,
|
|
101
|
-
content_id,
|
|
102
|
-
key=local_key,
|
|
103
|
-
learner_downloadable=True,
|
|
104
|
-
)
|
|
105
81
|
|
|
106
82
|
self.stdout.write(
|
|
107
83
|
f"Created v{next_version.version_num} of "
|
|
@@ -6,6 +6,7 @@ more intelligent data models to be useful.
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
8
|
from functools import cache, cached_property
|
|
9
|
+
from logging import getLogger
|
|
9
10
|
|
|
10
11
|
from django.conf import settings
|
|
11
12
|
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
|
@@ -19,6 +20,8 @@ from ....lib.fields import MultiCollationTextField, case_insensitive_char_field,
|
|
|
19
20
|
from ....lib.managers import WithRelationsManager
|
|
20
21
|
from ..publishing.models import LearningPackage
|
|
21
22
|
|
|
23
|
+
logger = getLogger()
|
|
24
|
+
|
|
22
25
|
__all__ = [
|
|
23
26
|
"MediaType",
|
|
24
27
|
"Content",
|
|
@@ -316,8 +319,11 @@ class Content(models.Model):
|
|
|
316
319
|
|
|
317
320
|
This will return ``None`` if there is no backing file (has_file=False).
|
|
318
321
|
"""
|
|
319
|
-
|
|
320
|
-
|
|
322
|
+
try:
|
|
323
|
+
if self.has_file:
|
|
324
|
+
return get_storage().path(self.path)
|
|
325
|
+
except NotImplementedError:
|
|
326
|
+
logger.warning("Storage backend does not support path()")
|
|
321
327
|
return None
|
|
322
328
|
|
|
323
329
|
def read_file(self) -> File:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: openedx-learning
|
|
3
|
-
Version: 0.16.
|
|
3
|
+
Version: 0.16.3
|
|
4
4
|
Summary: Open edX Learning Core and Tagging.
|
|
5
5
|
Home-page: https://github.com/openedx/openedx-learning
|
|
6
6
|
Author: David Ormsbee
|
|
@@ -18,12 +18,12 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Requires-Python: >=3.11
|
|
20
20
|
License-File: LICENSE.txt
|
|
21
|
-
Requires-Dist: attrs
|
|
22
|
-
Requires-Dist: celery
|
|
23
|
-
Requires-Dist: rules<4.0
|
|
24
|
-
Requires-Dist: Django<5.0
|
|
25
21
|
Requires-Dist: edx-drf-extensions
|
|
22
|
+
Requires-Dist: Django<5.0
|
|
23
|
+
Requires-Dist: celery
|
|
26
24
|
Requires-Dist: djangorestframework<4.0
|
|
25
|
+
Requires-Dist: attrs
|
|
26
|
+
Requires-Dist: rules<4.0
|
|
27
27
|
|
|
28
28
|
Open edX Learning Core (and Tagging)
|
|
29
29
|
====================================
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/api/authoring_models.py
RENAMED
|
File without changes
|
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/contents/api.py
RENAMED
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/apps/authoring/contents/apps.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/contrib/media_server/apps.py
RENAMED
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/contrib/media_server/urls.py
RENAMED
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning/contrib/media_server/views.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_learning.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/models/__init__.py
RENAMED
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/models/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/models/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/urls.py
RENAMED
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openedx_learning-0.16.1 → openedx_learning-0.16.3}/openedx_tagging/core/tagging/rest_api/v1/urls.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|