refactor: update openedx_content contents -> media(#38037)

Update our calls to the openedx_content API to reflect 0.35.0's shift
in terminology from "contents" to "media".

---------

Co-authored-by: Kyle McCormick <kyle@axim.org>
This commit is contained in:
David Ormsbee
2026-02-23 22:34:33 -05:00
committed by GitHub
parent e5ebde83f2
commit 873f42ab14
13 changed files with 74 additions and 74 deletions

View File

@@ -296,7 +296,7 @@ def _import_assets(migration: models.ModulestoreMigration) -> dict[str, int]:
filename = os.path.basename(old_path)
media_type_str = mimetypes.guess_type(filename)[0] or "application/octet-stream"
media_type = content_api.get_or_create_media_type(media_type_str)
content_by_filename[filename] = content_api.get_or_create_file_content(
content_by_filename[filename] = content_api.get_or_create_file_media(
migration.target_id,
media_type.id,
data=file_data,
@@ -969,13 +969,13 @@ def _migrate_component(
# If component existed and was deleted or we have to replace the current version
# Create the new component version for it
component_version = libraries_api.set_library_block_olx(target_key, new_olx_str=olx)
for filename, content_pk in context.content_by_filename.items():
for filename, media_pk in context.content_by_filename.items():
filename_no_ext, _ = os.path.splitext(filename)
if filename_no_ext not in olx:
continue
new_path = f"static/{filename}"
content_api.create_component_version_content(
component_version.pk, content_pk, key=new_path
content_api.create_component_version_media(
component_version.pk, media_pk, key=new_path
)
# Publish the component

View File

@@ -405,13 +405,13 @@ class TestMigrateFromModulestore(ModuleStoreTestCase):
olx = '<problem display_name="Test Problem"><p>See image: test_image.png</p></problem>'
media_type = content_api.get_or_create_media_type("image/png")
test_content = content_api.get_or_create_file_content(
test_media = content_api.get_or_create_file_media(
self.learning_package.id,
media_type.id,
data=b"fake_image_data",
created=timezone.now(),
)
content_by_filename = {"test_image.png": test_content.id}
content_by_filename = {"test_image.png": test_media.id}
context = self._make_migration_context(content_by_filename=content_by_filename)
result, reason = _migrate_component(
context=context,
@@ -423,11 +423,11 @@ class TestMigrateFromModulestore(ModuleStoreTestCase):
self.assertIsNotNone(result)
self.assertIsNone(reason)
component_content = result.componentversion.componentversioncontent_set.filter(
component_media = result.componentversion.componentversionmedia_set.filter(
key="static/test_image.png"
).first()
self.assertIsNotNone(component_content)
self.assertEqual(component_content.content_id, test_content.id)
self.assertIsNotNone(component_media)
self.assertEqual(component_media.media.id, test_media.id)
def test_migrate_skip_repeats(self):
"""
@@ -638,13 +638,13 @@ class TestMigrateFromModulestore(ModuleStoreTestCase):
olx = '<problem display_name="Test Problem"><p>See image: referenced.png</p></problem>'
media_type = content_api.get_or_create_media_type("image/png")
referenced_content = content_api.get_or_create_file_content(
referenced_content = content_api.get_or_create_file_media(
self.learning_package.id,
media_type.id,
data=b"referenced_image_data",
created=timezone.now(),
)
unreferenced_content = content_api.get_or_create_file_content(
unreferenced_content = content_api.get_or_create_file_media(
self.learning_package.id,
media_type.id,
data=b"unreferenced_image_data",
@@ -670,12 +670,12 @@ class TestMigrateFromModulestore(ModuleStoreTestCase):
self.assertIsNone(reason)
referenced_content_exists = (
result.componentversion.componentversioncontent_set.filter(
result.componentversion.componentversionmedia_set.filter(
key="static/referenced.png"
).exists()
)
unreferenced_content_exists = (
result.componentversion.componentversioncontent_set.filter(
result.componentversion.componentversionmedia_set.filter(
key="static/unreferenced.png"
).exists()
)
@@ -722,7 +722,7 @@ class TestMigrateFromModulestore(ModuleStoreTestCase):
)
child_version_1 = content_api.create_next_component_version(
child_component_1.pk,
content_to_replace={},
media_to_replace={},
created=timezone.now(),
created_by=self.user.id,
)
@@ -738,7 +738,7 @@ class TestMigrateFromModulestore(ModuleStoreTestCase):
)
child_version_2 = content_api.create_next_component_version(
child_component_2.pk,
content_to_replace={},
media_to_replace={},
created=timezone.now(),
created_by=self.user.id,
)
@@ -910,7 +910,7 @@ class TestMigrateFromModulestore(ModuleStoreTestCase):
)
child_version = content_api.create_next_component_version(
child_component.pk,
content_to_replace={},
media_to_replace={},
created=timezone.now(),
created_by=self.user.id,
)
@@ -950,7 +950,7 @@ class TestMigrateFromModulestore(ModuleStoreTestCase):
)
problem_version = content_api.create_next_component_version(
problem_component.pk,
content_to_replace={},
media_to_replace={},
created=timezone.now(),
created_by=self.user.id,
)
@@ -966,7 +966,7 @@ class TestMigrateFromModulestore(ModuleStoreTestCase):
)
html_version = content_api.create_next_component_version(
html_component.pk,
content_to_replace={},
media_to_replace={},
created=timezone.now(),
created_by=self.user.id,
)
@@ -982,7 +982,7 @@ class TestMigrateFromModulestore(ModuleStoreTestCase):
)
video_version = content_api.create_next_component_version(
video_component.pk,
content_to_replace={},
media_to_replace={},
created=timezone.now(),
created_by=self.user.id,
)

View File

@@ -238,7 +238,7 @@ def set_library_block_olx(usage_key: LibraryUsageLocatorV2, new_olx_str: str) ->
now = datetime.now(tz=timezone.utc)
with transaction.atomic():
new_content = content_api.get_or_create_text_content(
new_content = content_api.get_or_create_text_media(
component.learning_package_id,
get_or_create_olx_media_type(usage_key.block_type).id,
text=new_olx_str,
@@ -247,7 +247,7 @@ def set_library_block_olx(usage_key: LibraryUsageLocatorV2, new_olx_str: str) ->
new_component_version = content_api.create_next_component_version(
component.pk,
title=new_title,
content_to_replace={
media_to_replace={
'block.xml': new_content.pk,
},
created=now,
@@ -481,13 +481,13 @@ def _import_staged_block(
media_type_str = "application/octet-stream"
media_type = content_api.get_or_create_media_type(media_type_str)
content = content_api.get_or_create_file_content(
content = content_api.get_or_create_file_media(
learning_package.id,
media_type.id,
data=file_data,
created=now,
)
content_api.create_component_version_content(
content_api.create_component_version_media(
component_version.pk,
content.id,
key=filename,
@@ -833,30 +833,30 @@ def get_library_block_static_asset_files(usage_key: LibraryUsageLocatorV2) -> li
if component_version is None:
return []
# cvc = the ComponentVersionContent through table
cvc_set = (
# cvm = the ComponentVersionMedia through table
cvm_set = (
component_version
.componentversioncontent_set
.filter(content__has_file=True)
.componentversionmedia_set
.filter(media__has_file=True)
.order_by('key')
.select_related('content')
.select_related('media')
)
site_root_url = get_xblock_app_config().get_site_root_url()
return [
LibraryXBlockStaticFile(
path=cvc.key,
size=cvc.content.size,
path=cvm.key,
size=cvm.media.size,
url=site_root_url + reverse(
'content_libraries:library-assets',
kwargs={
'component_version_uuid': component_version.uuid,
'asset_path': cvc.key,
'asset_path': cvm.key,
}
),
)
for cvc in cvc_set
for cvm in cvm_set
]
@@ -897,7 +897,7 @@ def add_library_block_static_asset_file(
with transaction.atomic():
component_version = content_api.create_next_component_version(
component.pk,
content_to_replace={file_path: file_content},
media_to_replace={file_path: file_content},
created=datetime.now(tz=timezone.utc),
created_by=user.id if user else None,
)
@@ -945,7 +945,7 @@ def delete_library_block_static_asset_file(usage_key, file_path, user=None):
with transaction.atomic():
component_version = content_api.create_next_component_version(
component.pk,
content_to_replace={file_path: None},
media_to_replace={file_path: None},
created=now,
created_by=user.id if user else None,
)
@@ -1038,13 +1038,13 @@ def _create_component_for_block(
created_by=user_id,
can_stand_alone=can_stand_alone,
)
content = content_api.get_or_create_text_content(
content = content_api.get_or_create_text_media(
learning_package.id,
get_or_create_olx_media_type(usage_key.block_type).id,
text=xml_text,
created=now,
)
content_api.create_component_version_content(
content_api.create_component_version_media(
component_version.pk,
content.id,
key="block.xml",

View File

@@ -423,8 +423,8 @@ def get_component_version_asset(request, component_version_uuid, asset_path):
return redirect_response
# If we got here, we know that the asset exists and it's okay to download.
cv_content = component_version.componentversioncontent_set.get(key=asset_path)
content = cv_content.content
cv_media = component_version.componentversionmedia_set.get(key=asset_path)
media = cv_media.media
# Delete the re-direct part of the response headers. We'll copy the rest.
headers = redirect_response.headers
@@ -433,7 +433,7 @@ def get_component_version_asset(request, component_version_uuid, asset_path):
# We need to set the content size header manually because this is a
# streaming response. It's not included in the redirect headers because it's
# not needed there (the reverse-proxy would have direct access to the file).
headers['Content-Length'] = content.size
headers['Content-Length'] = media.size
if request.method == "HEAD":
return HttpResponse(headers=headers)
@@ -442,7 +442,7 @@ def get_component_version_asset(request, component_version_uuid, asset_path):
# offsets or anything fancy, because we don't expect to run this view at
# LMS-scale.
return StreamingHttpResponse(
content.read_file().chunks(),
media.read_file().chunks(),
headers=redirect_response.headers,
)

View File

@@ -162,7 +162,7 @@ class ContentLibrariesComponentVersionAssetTest(ContentLibrariesRestApiTest):
)
assert response.status_code == 404
# File-like ComponenVersionContent entry that isn't an actually
# File-like ComponentVersionMedia entry that isn't an actually
# downloadable file...
response = self.client.get(
f"/library_assets/component_versions/{self.draft_component_version.uuid}/block.xml"

View File

@@ -1017,15 +1017,15 @@ def get_transcript_from_openedx_content(video_block, language, output_format, tr
# TODO: There should be a openedx_content API call for this:
try:
content = (
media = (
component_version
.componentversioncontent_set
.filter(content__has_file=True)
.select_related('content')
.componentversionmedia_set
.filter(media__has_file=True)
.select_related('media')
.get(key=file_path)
.content
.media
)
data = content.read_file().read()
data = media.read_file().read()
except ObjectDoesNotExist as exc:
raise NotFoundError(
f"No file {file_path} found for {usage_key} "

View File

@@ -235,9 +235,9 @@ def get_block_olx(
raise NoSuchUsage(usage_key)
# TODO: we should probably make a method on ComponentVersion that returns
# a content based on the name. Accessing by componentversioncontent__key is
# a content based on the name. Accessing by componentversionmedia__key is
# awkward.
content = component_version.contents.get(componentversioncontent__key="block.xml")
content = component_version.media.get(componentversionmedia__key="block.xml")
return content.text

View File

@@ -193,8 +193,8 @@ class OpenedXContentRuntime(XBlockRuntime):
if component_version is None:
raise NoSuchUsage(usage_key)
content = component_version.contents.get(
componentversioncontent__key="block.xml"
content = component_version.media.get(
componentversionmedia__key="block.xml"
)
xml_node = etree.fromstring(content.text)
block_type = usage_key.block_type
@@ -248,22 +248,22 @@ class OpenedXContentRuntime(XBlockRuntime):
"""
component_version = self.get_component_version_from_block(block)
# cvc = the ComponentVersionContent through-table
cvc_list = (
# cvm = the ComponentVersionMedia through-table
cvm_list = (
component_version
.componentversioncontent_set
.filter(content__has_file=True)
.select_related('content')
.componentversionmedia_set
.filter(media__has_file=True)
.select_related('media')
.order_by('key')
)
return [
StaticFile(
name=cvc.key,
url=self._absolute_url_for_asset(component_version, cvc.key),
data=cvc.content.read_file().read() if fetch_asset_data else None,
name=cvm.key,
url=self._absolute_url_for_asset(component_version, cvm.key),
data=cvm.media.read_file().read() if fetch_asset_data else None,
)
for cvc in cvc_list
for cvm in cvm_list
]
def save_block(self, block):
@@ -298,7 +298,7 @@ class OpenedXContentRuntime(XBlockRuntime):
block_media_type = content_api.get_or_create_media_type(
f"application/vnd.openedx.xblock.v1.{usage_key.block_type}+xml"
)
content = content_api.get_or_create_text_content(
media = content_api.get_or_create_text_media(
component.learning_package_id,
block_media_type.id,
text=serialized.olx_str,
@@ -307,8 +307,8 @@ class OpenedXContentRuntime(XBlockRuntime):
content_api.create_next_component_version(
component.pk,
title=block.display_name,
content_to_replace={
"block.xml": content.id,
media_to_replace={
"block.xml": media.id,
},
created=now,
created_by=self.user.id if self.user else None
@@ -446,10 +446,10 @@ class OpenedXContentRuntime(XBlockRuntime):
component_version = self.get_component_version_from_block(block)
try:
content = (
media = (
component_version
.componentversioncontent_set
.filter(content__has_file=True)
.componentversionmedia_set
.filter(media__has_file=True)
.get(key=f"static/{asset_path}")
)
except ObjectDoesNotExist:
@@ -457,10 +457,10 @@ class OpenedXContentRuntime(XBlockRuntime):
# Retry with unquoted path. We don't always unquote because it would not
# be backwards-compatible, but we need to try both.
asset_path = unquote(asset_path)
content = (
media = (
component_version
.componentversioncontent_set
.filter(content__has_file=True)
.componentversionmedia_set
.filter(media__has_file=True)
.get(key=f"static/{asset_path}")
)
except ObjectDoesNotExist:

View File

@@ -65,7 +65,7 @@ numpy<2.0.0
# breaking changes which openedx-core devs want to roll out manually. New patch versions
# are OK to accept automatically.
# Issue for unpinning: https://github.com/openedx/edx-platform/issues/35269
openedx-core<0.35
openedx-core<0.36
# Date: 2023-11-29
# Open AI version 1.0.0 dropped support for openai.ChatCompletion which is currently in use in enterprise.

View File

@@ -808,7 +808,7 @@ openedx-authz==0.22.0
# via -r requirements/edx/kernel.in
openedx-calc==4.0.3
# via -r requirements/edx/kernel.in
openedx-core==0.34.2
openedx-core==0.35.0
# via
# -c requirements/constraints.txt
# -r requirements/edx/kernel.in

View File

@@ -1365,7 +1365,7 @@ openedx-calc==4.0.3
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
openedx-core==0.34.2
openedx-core==0.35.0
# via
# -c requirements/constraints.txt
# -r requirements/edx/doc.txt

View File

@@ -984,7 +984,7 @@ openedx-authz==0.22.0
# via -r requirements/edx/base.txt
openedx-calc==4.0.3
# via -r requirements/edx/base.txt
openedx-core==0.34.2
openedx-core==0.35.0
# via
# -c requirements/constraints.txt
# -r requirements/edx/base.txt

View File

@@ -1034,7 +1034,7 @@ openedx-authz==0.22.0
# via -r requirements/edx/base.txt
openedx-calc==4.0.3
# via -r requirements/edx/base.txt
openedx-core==0.34.2
openedx-core==0.35.0
# via
# -c requirements/constraints.txt
# -r requirements/edx/base.txt