build!: Switch to openedx-core (renamed from openedx-learning) (#38011)

build!: Switch to openedx-core (renamed from openedx-learning)

Instead of installing openedx-learning==0.32.0, we install openedx-core==0.34.1.
We update various class names, function names, docstrings, and comments to
represent the rename:

* We say "openedx-core" when referring to the whole repo or PyPI project
  * or occasionally "Open edX Core" if we want it to look nice in the docs.
* We say "openedx_content" to refer to the Content API within openedx-core,
   which is actually the thing we have been calling "Learning Core" all along.
  * In snake-case code, it's `*_openedx_content_*`.
  * In camel-case code, it's `*OpenedXContent*`

For consistency's sake we avoid anything else like oex_core, OeXCore,
OpenEdXCore, OexContent, openedx-content, OpenEdxContent, etc.
There should be no more references to learning_core, learning-core, Learning Core,
Learning-Core, LC, openedx-learning, openedx_learning, etc.

BREAKING CHANGE: for openedx-learning/openedx-core developers:
You may need to uninstall openedx-learning and re-install openedx-core
from your venv. If running tutor, you may need to un-mount openedx-learning,
rename the directory to openedx-core, re-mount it, and re-build.
The code APIs themselves are fully backwards-compatible.

Part of: https://github.com/openedx/openedx-core/issues/470
This commit is contained in:
Kyle McCormick
2026-02-18 17:38:25 -05:00
committed by GitHub
parent 5e75d3cce4
commit c70bfe980a
70 changed files with 244 additions and 239 deletions

View File

@@ -614,7 +614,7 @@ def get_unit_tags(usage_key):
Get the tags of a Unit and build a json to be read by the UI
Note: When migrating the `TagList` subview from `container_subview.js` to the course-authoring MFE,
this function can be simplified to use the REST API of openedx-learning,
this function can be simplified to use the REST API of openedx_tagging,
which already provides this grouping + sorting logic.
"""
# Get content tags from content tagging API

View File

@@ -91,18 +91,18 @@ def link_video_to_component(video_component, user):
return edx_video_id
def save_video_transcript_in_learning_core(
def save_video_transcript_in_openedx_content(
usage_key,
input_format,
transcript_content,
language_code
):
"""
Saves a video transcript to the learning core.
Saves a video transcript with the openedx_content API.
Learning Core uses the standard `.srt` format for subtitles.
openedx_content uses the standard `.srt` format for subtitles.
Note: SJSON is an edx-specific format that we're trying to move away from,
so for all new stuff related to Learning Core should only use `.srt`.
so for all new stuff related to openedx_content should only use `.srt`.
Arguments:
usage_key: UsageKey of the block
@@ -615,7 +615,7 @@ def choose_transcripts(request):
# 3. Upload the retrieved transcript to DS for the linked video ID.
if isinstance(video.usage_key.context_key, LibraryLocatorV2):
success = save_video_transcript_in_learning_core(
success = save_video_transcript_in_openedx_content(
video.usage_key,
input_format,
transcript_content,
@@ -669,7 +669,7 @@ def rename_transcripts(request):
# 3. Upload the retrieved transcript to DS for the linked video ID.
if isinstance(video.usage_key.context_key, LibraryLocatorV2):
success = save_video_transcript_in_learning_core(
success = save_video_transcript_in_openedx_content(
video.usage_key,
input_format,
transcript_content,
@@ -725,7 +725,7 @@ def replace_transcripts(request):
for transcript in transcript_content:
[language_code, json_content] = transcript
if isinstance(video.usage_key.context_key, LibraryLocatorV2):
success = save_video_transcript_in_learning_core(
success = save_video_transcript_in_openedx_content(
video.usage_key,
Transcript.SJSON,
json_content,

View File

@@ -1,5 +1,5 @@
"""
A nice little admin interface for migrating courses and libraries from modulstore to Learning Core.
A nice little admin interface for migrating courses and libraries from modulstore to openedx_content.
"""
import logging

View File

@@ -47,7 +47,7 @@ __all__ = (
def get_forwarding_for_blocks(source_keys: t.Iterable[UsageKey]) -> dict[UsageKey, ModulestoreBlockMigrationSuccess]:
"""
Authoritatively determine how some Modulestore blocks have been migrated to Learning Core.
Authoritatively determine how some Modulestore blocks have been migrated to openedx_content.
Returns a mapping from source usage keys to block migration data objects. Each block migration object
holds the target usage key and title. If a source key is missing from the mapping, then it has not
@@ -79,7 +79,7 @@ def get_forwarding_for_blocks(source_keys: t.Iterable[UsageKey]) -> dict[UsageKe
def is_forwarded(source_key: SourceContextKey) -> bool:
"""
Has this course or legacy library been authoratively migrated to Learning Core,
Has this course or legacy library been authoratively migrated to openedx_content,
such that references to the source course/library should be forwarded to the target library?
"""
return get_forwarding(source_key) is not None
@@ -87,7 +87,7 @@ def is_forwarded(source_key: SourceContextKey) -> bool:
def get_forwarding(source_key: SourceContextKey) -> ModulestoreMigration | None:
"""
Authoritatively determine how some Modulestore course or legacy library has been migrated to Learning Core.
Authoritatively determine how some Modulestore course or legacy library has been migrated to openedx_content.
If no such successful migration exists, returns None.
@@ -123,7 +123,7 @@ def get_migrations(
is_failed: bool | None = None,
) -> t.Generator[ModulestoreMigration]:
"""
Given some criteria, get all modulestore->LearningCore migrations.
Given some criteria, get all modulestore->openedx_content migrations.
Returns an iterable, ordered from NEWEST to OLDEST.

View File

@@ -92,7 +92,7 @@ SourceContextKey: t.TypeAlias = CourseLocator | LibraryLocator
@dataclass(frozen=True)
class ModulestoreMigration:
"""
Metadata on a migration of a course or legacy library to a v2 library in learning core.
Metadata on a migration of a course or legacy library to a v2 library in openedx_content.
"""
pk: int
source_key: SourceContextKey
@@ -107,7 +107,7 @@ class ModulestoreMigration:
@dataclass(frozen=True)
class ModulestoreBlockMigrationResult:
"""
Base class for a modulestore block that was part of an attempted migration to learning core.
Base class for a modulestore block that was part of an attempted migration to openedx_content.
"""
source_key: UsageKey
is_failed: t.ClassVar[bool]
@@ -116,7 +116,7 @@ class ModulestoreBlockMigrationResult:
@dataclass(frozen=True)
class ModulestoreBlockMigrationSuccess(ModulestoreBlockMigrationResult):
"""
Info on a modulestore block which has been successfully migrated into an LC entity
Info on a modulestore block which has been successfully migrated to an openedx_content entity
"""
target_entity_pk: int
target_key: LibraryUsageLocatorV2 | LibraryContainerLocator
@@ -128,7 +128,7 @@ class ModulestoreBlockMigrationSuccess(ModulestoreBlockMigrationResult):
@dataclass(frozen=True)
class ModulestoreBlockMigrationFailure(ModulestoreBlockMigrationResult):
"""
Info on a modulestore block which failed to be migrated into LC
Info on a modulestore block which failed to be migrated into openedx_content
"""
unsupported_reason: str
is_failed: t.ClassVar[bool] = True

View File

@@ -68,7 +68,7 @@ class ModulestoreSource(models.Model):
class ModulestoreMigration(models.Model):
"""
Tracks the action of a user importing a Modulestore-based course or legacy library into a
learning-core based learning package
openedx_content based learning package
Notes:
* As of Ulmo, a learning package is always associated with a v2 content library, but we

View File

@@ -75,7 +75,7 @@ _error_responses = {
)
class MigrationViewSet(StatusViewSet):
"""
JSON HTTP API to create and check on ModuleStore-to-Learning-Core migration tasks.
JSON HTTP API to create and check on ModuleStore-to-openedx_content migration tasks.
"""
authentication_classes = (
@@ -257,7 +257,7 @@ class MigrationViewSet(StatusViewSet):
class BulkMigrationViewSet(StatusViewSet):
"""
JSON HTTP API to bulk-create ModuleStore-to-Learning-Core migration tasks.
JSON HTTP API to bulk-create ModuleStore-to-openedx_content migration tasks.
"""
authentication_classes = (

View File

@@ -61,7 +61,7 @@ log = get_task_logger(__name__)
class MigrationStep(Enum):
"""
Strings representation the state of an in-progress modulestore-to-learning-core import.
Strings representation the state of an in-progress modulestore-to-openedx_content import.
We use these values to set UserTaskStatus.state.
The other possible UserTaskStatus.state values are the built-in ones:
@@ -313,16 +313,16 @@ def _import_structure(
status: UserTaskStatus,
) -> tuple[t.Any, _MigratedNode]:
"""
Import the staged content structure into the target Learning Core library.
Import the staged content structure into the target openedx_content library.
Args:
migration (ModulestoreMigration):
The migration record representing the ongoing modulestore-to-learning-core migration.
The migration record representing the ongoing modulestore-to-openedx_content migration.
source_data (_MigrationSourceData):
Data extracted from the legacy modulestore, including the source root usage key.
Use `_validate_input()` to generate this data.
target_library (libraries_api.ContentLibraryMetadata):
The target library where the new Learning Core content will be created.
The target library where the new openedx_content content will be created.
content_by_filename (dict[str, int]):
A mapping between OLX file names and their associated file IDs in the staging area.
Use `_import_assets` to generate this content.
@@ -338,7 +338,7 @@ def _import_structure(
`content_api.bulk_draft_changes_for`, containing all the imported changes.
- The second element (`root_migrated_node`): a `_MigratedNode` object that
represents the mapping between the legacy root node and its newly created
Learning Core equivalent.
openedx_content equivalent.
"""
migration = source_data.migration
migration_context = _MigrationContext(

View File

@@ -712,7 +712,7 @@ INSTALLED_APPS = [
'cms.djangoapps.export_course_metadata.apps.ExportCourseMetadataConfig',
'cms.djangoapps.modulestore_migrator',
# New (Learning-Core-based) XBlock runtime
# New (openedx_content-based) XBlock runtime
'openedx.core.djangoapps.xblock.apps.StudioXBlockAppConfig',
'openedx.core.djangoapps.util.apps.UtilConfig',

View File

@@ -210,7 +210,7 @@ for theme_dir in COMPREHENSIVE_THEME_DIRS: # pylint: disable=not-an-iterable
RATELIMIT_RATE = '2/m'
############## openedx-learning (Learning Core) config ##############
############## openedx_content config ##############
OPENEDX_LEARNING = {
"MEDIA": {"BACKEND": "django.core.files.storage.InMemoryStorage", "OPTIONS": {"location": MEDIA_ROOT + "_private"}}
}

View File

@@ -3,7 +3,7 @@ Synchronize content and settings from upstream content to their downstream
usages.
At the time of writing, we assume that for any upstream-downstream linkage:
* The upstream is a Component or Container from a Learning Core-backed Content
* The upstream is a Component or Container from a openedx_content-backed Content
Library.
* The downstream is a block of compatible type in a SplitModuleStore-backed
Course.
@@ -245,7 +245,7 @@ class UpstreamLink:
Get info on a downstream block's relationship with its linked upstream
content (without actually loading the content).
Currently, the only supported upstreams are LC-backed Library Components
Currently, the only supported upstreams are openedx_content-backed Components
(XBlocks) or Containers. This may change in the future (see module
docstring).

View File

@@ -90,8 +90,8 @@ def _load_upstream_block(downstream: XBlock, user: User) -> XBlock:
"""
Load the upstream metadata and content for a downstream block.
Assumes that the upstream content is an XBlock in an LC-backed content libraries. This assumption may need to be
relaxed in the future (see module docstring).
Assumes that the upstream content is an XBlock in an openedx_content-backed
library. This assumption may need to be relaxed in the future (see module docstring).
If `downstream` lacks a valid+supported upstream link, this raises an UpstreamLinkException.
"""

View File

@@ -48,7 +48,7 @@ def course_context_from_course_id(course_id):
"""
Creates a course context from a `course_id`.
For newer parts of the system (i.e. Learning-Core-based libraries/courses/etc.)
For newer parts of the system (i.e. openedx_content-based libraries/courses/etc.)
use context_dict_for_learning_context instead of this method.
Example Returned Context::

View File

@@ -286,7 +286,7 @@
// Does the XBlock HTML contain arguments to pass to the InitFunction?
let data = {};
[].forEach.call(element.children, (childNode) => {
// The newer/pure/LearningCore runtime uses 'xblock_json_init_args'
// The newer/pure/openedx_content runtime uses 'xblock_json_init_args'
// while the LMS runtime uses 'xblock-json-init-args'.
if (
childNode.matches('script.xblock_json_init_args')
@@ -405,13 +405,13 @@
//
// Here that is an issue because we show a confirmation modal when clicking cancel,
// if the user stays to edit all TinyMCE editors are no longer there.
//
//
// We uncouple the listener to avoid remove the TinyMCE editors
const extraCancelSelector = '.cancel-button';
const elements = $(extraCancelSelector).first();
if (elements.length) {
elements.first().unbind("click");
elements.on('click', function() {
elements.on('click', function() {
event.preventDefault();
runtime.notify('cancel', {});
});
@@ -421,7 +421,7 @@
// Recursively initialize the JavaScript code of each XBlock:
function initializeXBlockAndChildren(element, callback) {
// The newer/pure/LearningCore runtime uses the 'data-usage' attribute, while the LMS uses 'data-usage-id'
// The newer/pure/openedx_content runtime uses the 'data-usage' attribute, while the LMS uses 'data-usage-id'
const usageId = element.getAttribute('data-usage') || element.getAttribute('data-usage-id');
if (usageId !== null) {
element[USAGE_ID_KEY] = usageId;
@@ -461,7 +461,7 @@
}
// Find the root XBlock node.
// The newer/pure/LearningCore runtime uses '.xblock-v1' while the LMS runtime uses '.xblock'.
// The newer/pure/openedx_content runtime uses '.xblock-v1' while the LMS runtime uses '.xblock'.
const rootNode = document.querySelector('.xblock, .xblock-v1'); // will always return the first matching element
initializeXBlockAndChildren(rootNode, () => {
});

View File

@@ -124,7 +124,7 @@ Here are the different integration points that python plugins can use:
- By default, the registration page for each instance of Open edX has fields that ask for information such as a users name, country, and highest level of education completed. You can add custom fields to the registration page for your own Open edX instance. These fields can be different types, including text entry fields and drop-down lists. See `Adding Custom Fields to the Registration Page`_.
* - Learning Context (``openedx.learning_context``)
- Trial, Limited
- A "Learning Context" is a course, a library, a program, a blog, an external site, or some other collection of content where learning happens. If you are trying to build a totally new learning experience that's not a type of course, you may need to implement a new learning context. Learning contexts are a new abstraction and are only supported in the nascent Learning-Core-based XBlock runtime. Since existing courses use modulestore instead of Learning Core, they are not yet implemented as learning contexts. However, Learning-Core-based content libraries are. See |learning_context.py|_ to learn more.
- A "Learning Context" is a course, a library, a program, a blog, an external site, or some other collection of content where learning happens. If you are trying to build a totally new learning experience that's not a type of course, you may need to implement a new learning context. Learning contexts are a new abstraction and are only supported in the nascent openedx_content-based XBlock runtime. Since existing courses use modulestore instead of openedx_content, they are not yet implemented as learning contexts. However, openedx_content-based content libraries are. See |learning_context.py|_ to learn more.
* - User partition scheme (``openedx.user_partition_scheme`` and ``openedx.dynamic_partition_generator``)
- Unknown, Stable
- A user partition scheme is a named way for dividing users in a course into groups, usually to show different content to different users or to run experiments. Partitions may be added to a course manually, or automatically added by a "dynamic partition generator." The core platform includes partition scheme plugins like ``random``, ``cohort``, and ``enrollment_track``. See the |UserPartition docstring|_ to learn more.

View File

@@ -13,7 +13,7 @@ Context
We are replacing the existing Legacy ("V1") Content Libraries system, based on
ModuleStore, with a Relaunched ("V2") Content Libraries system, based on
Learning Core. V1 and V2 libraries will coexist for at least one release to
openedx_content. V1 and V2 libraries will coexist for at least one release to
allow for migration; eventually, V1 libraries will be removed entirely.
Content from V1 libraries can only be included into courses using the

View File

@@ -167,9 +167,9 @@ class EdxNotesDecoratorTest(ModuleStoreTestCase):
self.problem.runtime.is_author_mode = True
assert 'original_get_html' == self.problem.get_html()
def test_edxnotes_learning_core_runtime(self):
def test_edxnotes_openedx_content_runtime(self):
"""
Tests that get_html is not wrapped when problem is rendered by the learning core runtime.
Tests that get_html is not wrapped when problem is rendered by the openedx_content runtime.
"""
del self.problem.block.runtime.modulestore
assert 'original_get_html' == self.problem.get_html()

View File

@@ -1780,7 +1780,7 @@ INSTALLED_APPS = [
# User tours
'lms.djangoapps.user_tours',
# New (Learning-Core-based) XBlock runtime
# New XBlock runtime, based on openedx_content
'openedx.core.djangoapps.xblock.apps.LmsXBlockAppConfig',
# Student support tools

View File

@@ -344,7 +344,7 @@ urlpatterns += [
name='xblock_resource_url',
),
# New (Learning-Core-based) XBlock REST API
# New XBlock REST API, based on the openedx_content API
path('', include(('openedx.core.djangoapps.xblock.rest_api.urls', 'openedx.core.djangoapps.xblock'),
namespace='xblock_api')),

View File

@@ -137,7 +137,7 @@ def meili_id_from_opaque_key(key: OpaqueKey) -> str:
hyphens (-) and underscores (_). Since our opaque keys don't meet this
requirement, we transform them to a similar slug ID string that does.
In the future, with Learning Core's data models in place for courseware,
In the future, with openedx_content's data models in place for courseware,
we could use PublishableEntity's primary key / UUID instead.
"""
# The slugified key _may_ not be unique so we append a hashed string to make it unique:
@@ -232,7 +232,9 @@ def _fields_from_block(block) -> dict:
if hasattr(block, "edited_on"):
block_data[Fields.modified] = block.edited_on.timestamp()
# Get the breadcrumbs (course, section, subsection, etc.):
if block.usage_key.context_key.is_course: # Getting parent is not yet implemented in Learning Core (for libraries).
# TODO: Implement this for library items too. Libraries didn't support hierarchy at the time
# this code was originally written.
if block.usage_key.context_key.is_course:
cur_block = block
while cur_block.parent:
if not cur_block.has_cached_parent:

View File

@@ -439,7 +439,7 @@ def _import_staged_block(
# The ``data`` attribute is going to be None because the clipboard
# is optimized to not do redundant file copying when copying/pasting
# within the same course (where all the Files and Uploads are
# shared). Learning Core backed content Components will always store
# shared). openedx_content backed content Components will always store
# a Component-local "copy" of the data, and rely on lower-level
# deduplication to happen in the ``contents`` app.
filename = staged_content_file_data.filename
@@ -459,14 +459,14 @@ def _import_staged_block(
# Courses don't support having assets that are local to a specific
# component, and instead store all their content together in a
# shared Files and Uploads namespace. If we're pasting that into a
# Learning Core backed data model (v2 Libraries), then we want to
# openedx_content backed data model (v2 Libraries), then we want to
# prepend "static/" to the filename. This will need to get updated
# when we start moving courses over to Learning Core, or if we start
# when we start moving courses over to openedx_content, or if we start
# storing course component assets in sub-directories of Files and
# Uploads.
#
# The reason we don't just search for a "static/" prefix is that
# Learning Core components can store other kinds of files if they
# openedx_content components can store other kinds of files if they
# wish (though none currently do).
source_assumes_global_assets = not isinstance(
source_context_key, LibraryLocatorV2
@@ -474,8 +474,8 @@ def _import_staged_block(
if source_assumes_global_assets:
filename = f"static/{filename}"
# Now construct the Learning Core data models for it...
# TODO: more of this logic should be pushed down to openedx-learning
# Now construct the Core data models for it...
# TODO: more of this logic should be pushed down to openedx_content
media_type_str, _encoding = mimetypes.guess_type(filename)
if not media_type_str:
media_type_str = "application/octet-stream"
@@ -687,7 +687,7 @@ def get_or_create_olx_media_type(block_type: str) -> MediaType:
"""
Get or create a MediaType for the block type.
Learning Core stores all Content with a Media Type (a.k.a. MIME type). For
openedx_content stores all Content with a Media Type (a.k.a. MIME type). For
OLX, we use the "application/vnd.*" convention, per RFC 6838.
"""
return content_api.get_or_create_media_type(

View File

@@ -24,7 +24,7 @@ from opaque_keys.edx.locator import (
from opaque_keys.edx.keys import UsageKey
from edx_rest_api_client.client import OAuthAPIClient
from openedx.core.lib.xblock_serializer.api import serialize_modulestore_block_for_learning_core
from openedx.core.lib.xblock_serializer.api import serialize_modulestore_block_for_openedx_content
from xmodule.modulestore.django import modulestore
from .. import tasks
@@ -209,7 +209,7 @@ class EdxModulestoreImportClient(BaseEdxImportClient):
Get block OLX by serializing it from modulestore directly.
"""
block = self.modulestore.get_item(block_key)
data = serialize_modulestore_block_for_learning_core(block)
data = serialize_modulestore_block_for_openedx_content(block)
return {'olx': data.olx_str,
'static_files': {s.name: s for s in data.static_files}}

View File

@@ -303,7 +303,7 @@ def get_libraries_for_user(user, org=None, text_search=None, order=None) -> Quer
def get_metadata(queryset: QuerySet[ContentLibrary], text_search: str | None = None) -> list[ContentLibraryMetadata]:
"""
Take a list of ContentLibrary objects and return metadata from Learning Core.
Take a list of ContentLibrary objects and return metadata from openedx_content.
"""
if text_search:
queryset = queryset.filter(org__short_name__icontains=text_search)
@@ -322,7 +322,7 @@ def get_metadata(queryset: QuerySet[ContentLibrary], text_search: str | None = N
allow_public_read=lib.allow_public_read,
# These are currently dummy values to maintain the REST API contract
# while we shift to Learning Core models.
# while we shift to openedx_content models.
num_blocks=0,
last_published=None,
has_unpublished_changes=False,
@@ -374,7 +374,7 @@ def get_library(library_key: LibraryLocatorV2) -> ContentLibraryMetadata:
# TODO: I'm doing this one to match already-existing behavior, but this is
# something that we should remove. It exists to accomodate some complexities
# with how Blockstore staged changes, but Learning Core works differently,
# with how Blockstore staged changes, but openedx_content works differently,
# and has_unpublished_changes should be sufficient.
# Ref: https://github.com/openedx/edx-platform/issues/34283
has_unpublished_deletes = (

View File

@@ -16,7 +16,7 @@ class ContentLibrariesConfig(AppConfig):
"""
name = 'openedx.core.djangoapps.content_libraries'
verbose_name = 'Content Libraries (Learning-Core-based)'
verbose_name = 'Content Libraries'
# This is designed as a plugin for now so that
# the whole thing is self-contained and can easily be enabled/disabled
plugin_app = {

View File

@@ -11,14 +11,14 @@ In Dec 2023, we decided to remove the code supporting this decision, because:
* The index is disabled on edx.org, which will initially be the only user
of Content Libraries V2.
* As we migrate libraries from Modulestore to Blockstore and then from
Blockstore to Learning Core, the unused indexing code increases complexity
Blockstore to openedx_content, the unused indexing code increases complexity
and decreases certainty.
* With the decision to migrate from Blockstore-the-service to an in-process
storage backend (that is: Blockstore-the-app or Learning Core), it seems
storage backend (that is: Blockstore-the-app or openedx_content), it seems
that we will be able to simply use Django ORM in order to filter/sort/search
Content Library V2 metadata for the library listing page.
* Searching Content Library V2 *block* content would still require indexing,
but we would rather implement that in Learning Core than use the current
but we would rather implement that in openedx_content than use the current
implementation in the content_libraries app, which is untested, library-
specific, and doesn't take into account library versioning. It always uses
the latest draft, which is good for Library Authoring purposes, but not good for

View File

@@ -24,7 +24,7 @@ class LibraryContextImpl(LearningContext):
"""
Implements content libraries as a learning context.
This is the *new* content libraries based on Learning Core, not the old content
This is the *new* content libraries based on openedx_content, not the old content
libraries based on modulestore.
"""

View File

@@ -89,7 +89,7 @@ class Command(BaseCommand):
def handle(self, *args, **options):
"""
Collect all blocks from a course that are "importable" and write them to the
a learning core library.
a openedx_content library.
"""
# Search for the library.

View File

@@ -8,7 +8,7 @@ This module contains the models for new Content Libraries.
LTI 1.3 Models
==============
Content Libraries serves learning-core-based content through LTI 1.3 launches.
Content Libraries serves openedx_content-based through LTI 1.3 launches.
The interface supports resource link launches and grading services. Two use
cases justify the current data model to support LTI launches. They are:
@@ -27,7 +27,7 @@ Relationship with LMS's ``lti_provider``` models
The data model above is similar to the one provided by the current LTI 1.1
implementation for modulestore and courseware content. But, Content Libraries
is orthogonal. Its use-case is to offer standalone, embedded content from a
specific backend (learning core). As such, it decouples from LTI 1.1. and the
specific backend (openedx_content). As such, it decouples from LTI 1.1. and the
logic assume no relationship or impact across the two applications. The same
reasoning applies to steps beyond the data model, such as at the XBlock
runtime, authentication, and score handling, etc.
@@ -85,9 +85,9 @@ class ContentLibrary(models.Model):
"""
A Content Library is a collection of content (XBlocks and/or static assets)
All actual content is stored in Learning Core, and any data that we'd want to
All actual content is stored in openedx_content, and any data that we'd want to
transfer to another instance if this library were exported and then
re-imported on another Open edX instance should be kept in Learning Core. This
re-imported on another Open edX instance should be kept in openedx_content. This
model in Studio should only be used to track settings specific to this Open
edX instance, like who has permission to edit this content library.

View File

@@ -1,5 +1,5 @@
"""
Permissions for Content Libraries (v2, Learning-Core-based)
Permissions for Content Libraries (v2, openedx_content-based)
"""
from bridgekeeper import perms, rules
from bridgekeeper.rules import Attribute, ManyRelation, Relation, blanket_rule, in_current_groups, Rule

View File

@@ -194,7 +194,7 @@ class LibraryBlockAssetView(APIView):
file_wrapper = request.data['content']
if file_wrapper.size > 20 * 1024 * 1024: # > 20 MiB
# TODO: This check was written when V2 Libraries were backed by the Blockstore micro-service.
# Now that we're on Learning Core, do we still need it? Here's the original comment:
# Now that we're on openedx_content, do we still need it? Here's the original comment:
# In the future, we need a way to use file_wrapper.chunks() to read
# the file in chunks and stream that to Blockstore, but Blockstore
# currently lacks an API for streaming file uploads.
@@ -406,7 +406,7 @@ def get_component_version_asset(request, component_version_uuid, asset_path):
)
# We already have logic for getting the correct content and generating the
# proper headers in Learning Core, but the response generated here is an
# proper headers in openedx_content, but the response generated here is an
# X-Accel-Redirect and lacks the actual content. We eventually want to use
# this response in conjunction with a media reverse proxy (Caddy or Nginx),
# but in the short term we're just going to remove the redirect and stream

View File

@@ -3,7 +3,7 @@
Content Libraries Views
=======================
This module contains the REST APIs for Learning Core-based content libraries,
This module contains the REST APIs for openedx_content-based content libraries,
and LTI 1.3 views (though I'm not sure how functional the LTI piece of this is
right now).
@@ -59,7 +59,7 @@ the api module instead.
Historical note: These views used to be wrapped with @atomic because we
wanted to make all views that operated on Blockstore (the predecessor
to Learning Core) atomic:
to openedx_content) atomic:
https://github.com/openedx/edx-platform/pull/30456
"""
import itertools

View File

@@ -198,7 +198,7 @@ class LibraryXBlockCreationSerializer(serializers.Serializer):
block_type = serializers.CharField()
# TODO: Rename to ``block_id`` or ``slug``. The Learning Core XBlock runtime
# TODO: Rename to ``block_id`` or ``slug``. The openedx_content XBlock runtime
# doesn't use definition_ids, but this field is really just about requesting
# a specific block_id, e.g. the "best_tropical_vacation_spots" portion of a
# problem with UsageKey:

View File

@@ -4,11 +4,11 @@ Celery tasks for Content Libraries.
Architecture note:
Several functions in this file manage the copying/updating of blocks in modulestore
and learning core. These operations should only be performed within the context of CMS.
and openedx_content. These operations should only be performed within the context of CMS.
However, due to existing edx-platform code structure, we've had to define the functions
in shared source tree (openedx/) and the tasks are registered in both LMS and CMS.
To ensure that we're not accidentally importing things from learning core in the LMS context,
To ensure that we're not accidentally importing things from openedx_content in the LMS context,
we use ensure_cms throughout this module.
A longer-term solution to this issue would be to move the content_libraries app to cms:
@@ -183,7 +183,7 @@ def send_events_after_revert(draft_change_log_id: int, library_key_str: str) ->
try:
draft_change_log = DraftChangeLog.objects.get(id=draft_change_log_id)
except DraftChangeLog.DoesNotExist:
# When a revert operation is a no-op, Learning Core deletes the empty
# When a revert operation is a no-op, openedx_content deletes the empty
# DraftChangeLog, so we'll assume that's what happened here.
log.info(f"Library revert in {library_key_str} did not result in any changes.")
return

View File

@@ -1,5 +1,5 @@
"""
Tests for Learning-Core-based Content Libraries
Tests for openedx_content-based Content Libraries
"""
from contextlib import contextmanager
import json
@@ -67,7 +67,7 @@ URL_BLOCK_XBLOCK_HANDLER = '/api/xblock/v2/xblocks/{block_key}/handler/{user_id}
@skip_unless_cms # Content Libraries REST API is only available in Studio
class ContentLibrariesRestApiTest(APITransactionTestCase):
"""
Base class for Learning-Core-based Content Libraries test that use the REST API
Base class for openedx_content-based Content Libraries test that use the REST API
These tests use the REST API, which in turn relies on the Python API.
Some tests may use the python API directly if necessary to provide

View File

@@ -1,5 +1,5 @@
"""
Tests for Learning-Core-based Content Libraries
Tests for openedx_content-based Content Libraries
"""
from datetime import datetime, timezone
import textwrap
@@ -875,7 +875,7 @@ class ContainersTestCase(ContentLibrariesRestApiTest):
)
# TODO -- remove this when containers publish their children:
# https://github.com/openedx/openedx-learning/pull/307
# https://github.com/openedx/openedx-core/pull/307
# Removing the unit with components because the components (children of children) are not published.
# If the unit is kept, the subsection continues to have changes even after it is published.
self._remove_container_children(
@@ -951,7 +951,7 @@ class ContainersTestCase(ContentLibrariesRestApiTest):
)
# TODO -- remove this when containers publish their children:
# https://github.com/openedx/openedx-learning/pull/307
# https://github.com/openedx/openedx-core/pull/307
# Removing the subsection with units because the units (children of children) are not published.
# If the subsection is kept, the section continues to have changes even after it is published.
self._remove_container_children(

View File

@@ -1,5 +1,5 @@
"""
Tests for Learning-Core-based Content Libraries
Tests for openedx_content-based Content Libraries
"""
from datetime import datetime, timezone
import os
@@ -51,7 +51,7 @@ from ..permissions import CAN_VIEW_THIS_CONTENT_LIBRARY, HasPermissionInContentL
@ddt.ddt
class ContentLibrariesTestCase(ContentLibrariesRestApiTest):
"""
General tests for Learning-Core-based Content Libraries
General tests for openedx_content-based Content Libraries
These tests use the REST API, which in turn relies on the Python API.
Some tests may use the python API directly if necessary to provide
@@ -357,7 +357,7 @@ class ContentLibrariesTestCase(ContentLibrariesRestApiTest):
<problem display_name="New Multi Choice Question" max_attempts="5">
<multiplechoiceresponse>
<p>This is a normal capa problem with unicode 🔥. It has "maximum attempts" set to **5**.</p>
<label>Learning Core is designed to store.</label>
<label>openedx_content is designed to store.</label>
<choicegroup type="MultipleChoice">
<choice correct="false">XBlock metadata only</choice>
<choice correct="true">XBlock data/metadata and associated static asset files</choice>
@@ -382,7 +382,7 @@ class ContentLibrariesTestCase(ContentLibrariesRestApiTest):
# Now view the XBlock's student_view (including draft changes):
fragment = self._render_block_view(block_id, "student_view")
assert 'resources' in fragment
assert 'Learning Core is designed to store.' in fragment['content']
assert 'openedx_content is designed to store.' in fragment['content']
# Also call a handler to make sure that's working:
handler_url = self._get_block_handler_url(block_id, "xmodule_handler") + "problem_get"
@@ -576,7 +576,7 @@ class ContentLibrariesTestCase(ContentLibrariesRestApiTest):
TODO: The asset permissions part of this test have been commented out
for now. These should be re-enabled after we re-implement them over
Learning Core data models.
openedx_content data models.
"""
# Create a few users to use for all of these tests:
admin = UserFactory.create(username="Admin", email="admin@example.com", is_staff=True)
@@ -1678,7 +1678,7 @@ class ContentLibrariesAuthZTestCase(ContentLibrariesRestApiTest):
@ddt.ddt
class ContentLibraryXBlockValidationTest(APITestCase):
"""Tests only focused on service validation, no Learning Core interactions here."""
"""Tests only focused on service validation, no openedx_content interactions here."""
@ddt.data(
(URL_BLOCK_METADATA_URL, dict(block_key='totally_invalid_key')),

View File

@@ -1,5 +1,5 @@
"""
Tests for Imports from Courses to Learning-Core-based Content Libraries
Tests for Imports from Courses to openedx_content-based Content Libraries
"""
import ddt
from opaque_keys.edx.locator import LibraryContainerLocator

View File

@@ -24,7 +24,7 @@ from .fields_test_block import FieldsTestBlock
class LibrariesEmbedViewTestCase(ContentLibrariesRestApiTest):
"""
Tests for embed_view and interacting with draft/published/past versions of
Learning-Core-based XBlocks (in Content Libraries).
openedx_content-based XBlocks (in Content Libraries).
These tests use the REST API, which in turn relies on the Python API.
Some tests may use the python API directly if necessary to provide

View File

@@ -1,5 +1,5 @@
"""
Tests for Learning-Core-based Content Libraries
Tests for openedx_content-based Content Libraries
"""
from opaque_keys.edx.locator import (
LibraryCollectionLocator,
@@ -35,7 +35,7 @@ from openedx.core.djangolib.testing.utils import skip_unless_cms
@skip_unless_cms
class ContentLibrariesEventsTestCase(ContentLibrariesRestApiTest):
"""
Event tests for Learning-Core-based Content Libraries
Event tests for openedx_content-based Content Libraries
These tests use the REST API, which in turn relies on the Python API.
"""

View File

@@ -1,5 +1,5 @@
"""
Test the Learning-Core-based XBlock runtime and content libraries together.
Test the openedx_content-based XBlock runtime and content libraries together.
"""
import json
@@ -64,7 +64,7 @@ class ContentLibraryContentTestMixin:
@skip_unless_cms
class ContentLibraryOlxTests(ContentLibraryContentTestMixin, TestCase):
"""
Basic test of the Learning-Core-based XBlock serialization-deserialization, using XBlocks in a content library.
Basic test of the openedx_content-based XBlock serialization-deserialization, using XBlocks in a content library.
"""
def test_html_round_trip(self):
@@ -116,7 +116,7 @@ class ContentLibraryOlxTests(ContentLibraryContentTestMixin, TestCase):
f'<html url_name="roundtrip" display_name="Round Trip Test HTML Block"><![CDATA[{block_content}]]></html>\n'
)
# Save the block to LC, and re-load it.
# Save the block to openedx_content, and re-load it.
library_api.set_library_block_olx(usage_key, olx_1)
library_api.publish_changes(self.library.key)
block_saved_1 = xblock_api.load_block(usage_key, self.staff_user)
@@ -131,7 +131,7 @@ class ContentLibraryOlxTests(ContentLibraryContentTestMixin, TestCase):
).olx_str
assert olx_2 == canonical_olx
# Now, save that OLX back to LC, and re-load it again.
# Now, save that OLX back to openedx_content, and re-load it again.
library_api.set_library_block_olx(usage_key, olx_2)
library_api.publish_changes(self.library.key)
block_saved_2 = xblock_api.load_block(usage_key, self.staff_user)
@@ -149,7 +149,7 @@ class ContentLibraryOlxTests(ContentLibraryContentTestMixin, TestCase):
class ContentLibraryRuntimeTests(ContentLibraryContentTestMixin, TestCase):
"""
Basic tests of the Learning-Core-based XBlock runtime using XBlocks in a
Basic tests of the openedx_content-based XBlock runtime using XBlocks in a
content library.
"""
def test_dndv2_sets_translator(self):
@@ -180,7 +180,7 @@ class ContentLibraryRuntimeTests(ContentLibraryContentTestMixin, TestCase):
<problem display_name="New Multi Choice Question" max_attempts="5">
<multiplechoiceresponse>
<p>This is a normal capa problem. It has "maximum attempts" set to **5**.</p>
<label>Learning Core is designed to store.</label>
<label>openedx_content is designed to store.</label>
<choicegroup type="MultipleChoice">
<choice correct="false">XBlock metadata only</choice>
<choice correct="true">XBlock data/metadata and associated static asset files</choice>
@@ -471,7 +471,7 @@ class ContentLibraryXBlockUserStateTest(ContentLibraryContentTestMixin, TestCase
<problem display_name="New Multi Choice Question" max_attempts="5">
<multiplechoiceresponse>
<p>This is a normal capa problem. It has "maximum attempts" set to **5**.</p>
<label>Learning Core is designed to store.</label>
<label>openedx_content is designed to store.</label>
<choicegroup type="MultipleChoice">
<choice correct="false">XBlock metadata only</choice>
<choice correct="true">XBlock data/metadata and associated static asset files</choice>
@@ -543,7 +543,7 @@ class ContentLibraryXBlockUserStateTest(ContentLibraryContentTestMixin, TestCase
<problem display_name="New Multi Choice Question" max_attempts="5">
<multiplechoiceresponse>
<p>This is a normal capa problem. It has "maximum attempts" set to **5**.</p>
<label>Learning Core is designed to store.</label>
<label>openedx_content is designed to store.</label>
<choicegroup type="MultipleChoice">
<choice correct="false">XBlock metadata only</choice>
<choice correct="true">XBlock data/metadata and associated static asset files</choice>

View File

@@ -1,5 +1,5 @@
"""
Tests for static asset files in Learning-Core-based Content Libraries
Tests for static asset files in openedx_content-based Content Libraries
"""
from uuid import UUID
@@ -31,7 +31,7 @@ I'm Anant Agarwal, I'm the president of edX,
@skip_unless_cms
class ContentLibrariesStaticAssetsTest(ContentLibrariesRestApiTest):
"""
Tests for static asset files in Learning-Core-based Content Libraries
Tests for static asset files in openedx_content-based Content Libraries
"""
def test_asset_filenames(self):
@@ -72,7 +72,7 @@ class ContentLibrariesStaticAssetsTest(ContentLibrariesRestApiTest):
def test_video_transcripts(self):
"""
Test that video blocks can read transcript files out of learning core.
Test that video blocks can read transcript files out of openedx_content.
"""
library = self._create_library(slug="transcript-test-lib", title="Transcripts Test Library")
block = self._add_block_to_library(library["id"], "video", "video1")
@@ -111,7 +111,7 @@ class ContentLibrariesStaticAssetsTest(ContentLibrariesRestApiTest):
check_sjson()
check_download()
# Publish the OLX and the transcript file, since published data gets
# served differently by Learning Core and we should test that too.
# served differently by openedx_content and we should test that too.
self._commit_library_changes(library["id"])
check_sjson()
check_download()

View File

@@ -85,5 +85,5 @@ class LibraryBlockLtiUrlViewTest(
ContentLibrariesRestApiTest,
):
"""
Test generating LTI URL for a block in a library, using the installed Learning Core app.
Test generating LTI URL for a block in a library, using the installed openedx_content app.
"""

View File

@@ -17,7 +17,7 @@ As this app is designed only for ephemeral use cases, API consumers should not
expect that staged content will be stored for longer than 24 hours.
This app is part of the CMS and is not intended to work with the LMS. It may be
moved from the CMS into the future Learning Core project.
moved from the CMS into the future openedx_content project.
---------------
Clipboard Usage

View File

@@ -13,7 +13,7 @@ from common.djangoapps.student.auth import has_studio_read_access
from openedx.core.lib.api.view_utils import view_auth_classes
from xmodule.modulestore.django import modulestore
from openedx.core.lib.xblock_serializer.api import serialize_modulestore_block_for_learning_core
from openedx.core.lib.xblock_serializer.api import serialize_modulestore_block_for_openedx_content
@api_view(['GET'])
@@ -22,7 +22,7 @@ def get_block_olx(request, usage_key_str):
"""
Given a modulestore XBlock usage ID (block-v1:...), get its OLX and a list
of any static asset files it uses.
(There are other APIs for getting the OLX of Learning Core XBlocks.)
(There are other APIs for getting the OLX of openedx_content XBlocks.)
"""
# Parse the usage key:
try:
@@ -48,7 +48,7 @@ def get_block_olx(request, usage_key_str):
return
block = modulestore().get_item(block_key)
serialized_blocks[block_key] = serialize_modulestore_block_for_learning_core(block)
serialized_blocks[block_key] = serialize_modulestore_block_for_openedx_content(block)
if block.has_children:
for child_id in block.children:
@@ -103,7 +103,7 @@ def get_block_exportfs_file(request, usage_key_str, path):
raise PermissionDenied("You must be a member of the course team in Studio to export OLX using this API.")
block = modulestore().get_item(usage_key)
serialized = serialize_modulestore_block_for_learning_core(block)
serialized = serialize_modulestore_block_for_openedx_content(block)
static_file = None
for f in serialized.static_files:
if f.name == path:

View File

@@ -231,7 +231,7 @@ class VideoConfigService:
is_library = isinstance(video_block.usage_key.context_key, LibraryLocatorV2)
content: bytes = transcript_file.read()
if is_library:
# Save transcript as static asset in Learning Core if is a library component
# Save transcript as static asset in openedx_content if is a library component
filename = f'static/transcript-{new_language_code}.srt'
add_library_block_static_asset_file(video_block.usage_key, filename, content)
else:
@@ -355,7 +355,7 @@ class VideoConfigService:
def _save_transcript_field(video_block):
"""
Hacky workaround to ensure that transcript field is saved for Learning Core video blocks.
Hacky workaround to ensure that transcript field is saved for openedx_content video blocks.
It's not clear why this is necessary.
"""

View File

@@ -850,7 +850,7 @@ def get_transcript_for_video(video_location, subs_id, file_name, language):
"""
Get video transcript from content store. This is a lower level function and is used by
`get_transcript_from_contentstore`. Prefer that function instead where possible. If you
need to support getting transcripts from VAL or Learning Core as well, use the `get_transcript`
need to support getting transcripts from VAL or openedx_content as well, use the `get_transcript`
function instead.
NOTE: Transcripts can be searched from content store by two ways:
@@ -945,13 +945,13 @@ def build_components_import_path(usage_key, file_path):
return f"components/{usage_key.block_type}/{usage_key.block_id}/{file_path}"
def get_transcript_from_learning_core(video_block, language, output_format, transcripts_info):
def get_transcript_from_openedx_content(video_block, language, output_format, transcripts_info):
"""
Get video transcript from Learning Core (used for Content Libraries)
Get video transcript from the openedx_content API.
Limitation: This is only going to grab from the Draft version.
Learning Core models a VideoBlock's data in a more generic thing it calls a
openedx_content models a VideoBlock's data in a more generic thing it calls a
Component. Each Component has its own virtual space for file-like data. The
OLX for the VideoBlock itself is stored at the root of that space, as
``block.xml``. Static assets that are meant to be user-downloadable are
@@ -1015,7 +1015,7 @@ def get_transcript_from_learning_core(video_block, language, output_format, tran
f"transcript files, but we tried to look up {file_path} for {usage_key}"
)
# TODO: There should be a Learning Core API call for this:
# TODO: There should be a openedx_content API call for this:
try:
content = (
component_version
@@ -1074,8 +1074,8 @@ def get_transcript(video, lang=None, output_format=Transcript.SRT, youtube_id=No
lang = video.get_default_transcript_language(transcripts_info)
if isinstance(video.scope_ids.usage_id, UsageKeyV2):
# This block is in Learning Core.
return get_transcript_from_learning_core(video, lang, output_format, transcripts_info)
# This block is in openedx_content.
return get_transcript_from_openedx_content(video, lang, output_format, transcripts_info)
try:
edx_video_id = clean_video_id(video.edx_video_id)

View File

@@ -1,5 +1,5 @@
This README was written back when the new runtime was backed by Blockstore.
Now that the runtime is backed by Learning Core, this README is out of date.
Now that the runtime is backed by openedx_content, this README is out of date.
We need to audit and update it as part of
`this task <https://github.com/openedx/edx-platform/issues/34283>`_.

View File

@@ -28,9 +28,9 @@ from xblock.plugin import PluginMissingError
from openedx.core.types import User as UserType
from openedx.core.djangoapps.xblock.apps import get_xblock_app_config
from openedx.core.djangoapps.xblock.learning_context.manager import get_learning_context_impl
from openedx.core.djangoapps.xblock.runtime.learning_core_runtime import (
LearningCoreFieldData,
LearningCoreXBlockRuntime,
from openedx.core.djangoapps.xblock.runtime.openedx_content_runtime import (
OpenedXContentFieldData,
OpenedXContentRuntime,
)
from .data import CheckPerm, LatestVersion
from .rest_api.url_converters import VersionConverter
@@ -40,7 +40,7 @@ from .utils import (
get_auto_latest_version,
)
from .runtime.learning_core_runtime import LearningCoreXBlockRuntime
from .runtime.openedx_content_runtime import OpenedXContentRuntime
# Made available as part of this package's public API:
from openedx.core.djangoapps.xblock.learning_context import LearningContext
@@ -50,7 +50,7 @@ from openedx.core.djangoapps.xblock.learning_context import LearningContext
log = logging.getLogger(__name__)
def get_runtime(user: UserType | None) -> LearningCoreXBlockRuntime:
def get_runtime(user: UserType | None) -> OpenedXContentRuntime:
"""
Return a new XBlockRuntime.
@@ -62,9 +62,9 @@ def get_runtime(user: UserType | None) -> LearningCoreXBlockRuntime:
params = get_xblock_app_config().get_runtime_params()
params.update(
handler_url=get_handler_url,
authored_data_store=LearningCoreFieldData(),
authored_data_store=OpenedXContentFieldData(),
)
runtime = LearningCoreXBlockRuntime(user, **params)
runtime = OpenedXContentRuntime(user, **params)
return runtime
@@ -219,7 +219,7 @@ def get_block_olx(
version: int | LatestVersion = LatestVersion.AUTO
) -> str:
"""
Get the OLX source of the of the given Learning-Core-backed XBlock and a version.
Get the OLX source of the of the given openedx_content-backed XBlock and a version.
"""
component = get_component_from_usage_key(usage_key)
version = get_auto_latest_version(version)

View File

@@ -18,7 +18,7 @@ class XBlockAppConfig(AppConfig):
def get_runtime_params(self):
"""
Get the LearningCoreXBlockRuntime parameters appropriate for viewing and/or
Get the OpenedXContentRuntime parameters appropriate for viewing and/or
editing XBlock content.
"""
raise NotImplementedError
@@ -45,7 +45,7 @@ class LmsXBlockAppConfig(XBlockAppConfig):
def get_runtime_params(self):
"""
Get the LearningCoreXBlockRuntime parameters appropriate for viewing and/or
Get the OpenedXContentRuntime parameters appropriate for viewing and/or
editing XBlock content in the LMS
"""
return dict(
@@ -68,7 +68,7 @@ class StudioXBlockAppConfig(XBlockAppConfig):
def get_runtime_params(self):
"""
Get the LearningCoreXBlockRuntime parameters appropriate for viewing and/or
Get the OpenedXContentRuntime parameters appropriate for viewing and/or
editing XBlock content in Studio
"""
return dict(

View File

@@ -1,5 +1,5 @@
"""
Learning Core XBlock Runtime code
openedx_content XBlock Runtime code
"""
from __future__ import annotations
@@ -22,7 +22,7 @@ from xblock.fields import Field, Scope, ScopeIds
from xblock.field_data import FieldData
from openedx.core.djangoapps.xblock.api import get_xblock_app_config
from openedx.core.lib.xblock_serializer.api import serialize_modulestore_block_for_learning_core
from openedx.core.lib.xblock_serializer.api import serialize_modulestore_block_for_openedx_content
from openedx.core.lib.xblock_serializer.data import StaticFile
from ..data import AuthoredDataMode, LatestVersion
from ..utils import get_auto_latest_version
@@ -33,30 +33,30 @@ from .runtime import XBlockRuntime
log = logging.getLogger(__name__)
class LearningCoreFieldData(FieldData):
class OpenedXContentFieldData(FieldData):
"""
FieldData for the Learning Core XBlock Runtime
FieldData for the openedx_content XBlock Runtime
LearningCoreFieldData only supports the ``content`` and ``settings`` scopes.
OpenedXContentFieldData only supports the ``content`` and ``settings`` scopes.
Any attempt to read or write fields with other scopes will raise a
``NotImplementedError``. This class does NOT support the parent and children
scopes.
LearningCoreFieldData should only live for the duration of one request. The
interaction between LearningCoreXBlockRuntime and LearningCoreFieldData is
OpenedXContentFieldData should only live for the duration of one request. The
interaction between OpenedXContentRuntime and OpenedXContentFieldData is
as follows:
1. LearningCoreXBlockRuntime knows how retrieve authored content data from
the Learning Core APIs in openedx-learning. This content is stored as
OLX, and LearningCoreXBlockRuntime won't know how to parse it into
1. OpenedXContentRuntime knows how retrieve authored content data from
the Content API in openedx_content. This content is stored as
OLX, and OpenedXContentRuntime won't know how to parse it into
fields, since serialization logic can happen in the XBlock itself.
2. LearningCoreXBlockRuntime will then invoke the block to parse the OLX and
then force_save its field data into LearningCoreFieldData.
2. OpenedXContentRuntime will then invoke the block to parse the OLX and
then force_save its field data into OpenedXContentFieldData.
3. After this point, various handler and API calls might alter fields for
a given block using the XBlock.
4. The main thing that LearningCoreXBlockRuntime will want to know later on
4. The main thing that OpenedXContentRuntime will want to know later on
is whether it needs to write any changes when its save_block method is
invoked. To support this, LearningCoreFieldData needs to track which
invoked. To support this, OpenedXContentFieldData needs to track which
blocks have changes to any of their fields. See the marked_unchanged
method docstring for more details.
"""
@@ -74,9 +74,9 @@ class LearningCoreFieldData(FieldData):
Calling set or delete on a field always marks the block with that field
as changed, by adding its usage key to self.changed. But set() is also
called at the very beginning, when a block is first loaded from the
database by the LearningCoreXBlockRuntime's get_block call.
database by the OpenedXContentRuntime's get_block call.
This method exists so that LearningCoreXBlockRuntime can call it
This method exists so that OpenedXContentRuntime can call it
whenever it has either just done a get_block operation (because those
set() calls represent the already-persisted content state), or a
save_block operation (since those changes will have been persisted).
@@ -153,14 +153,14 @@ class LearningCoreFieldData(FieldData):
if field.scope not in (Scope.content, Scope.settings):
raise NotImplementedError(
f"Scope {field.scope} (field {name} of {block.scope_ids.usage_id}) "
"is unsupported. LearningCoreFieldData only supports the content"
"is unsupported. OpenedXContentFieldData only supports the content"
" and settings scopes."
)
class LearningCoreXBlockRuntime(XBlockRuntime):
class OpenedXContentRuntime(XBlockRuntime):
"""
XBlock runtime that uses openedx-learning apps for content storage.
XBlock runtime that uses openedx_content APIs (not ModuleStore).
The superclass is doing all the hard stuff. This class only only has to
worry about the block storage, block serialization/de-serialization, and
@@ -169,11 +169,11 @@ class LearningCoreXBlockRuntime(XBlockRuntime):
def get_block(self, usage_key, for_parent=None, *, version: int | LatestVersion = LatestVersion.AUTO):
"""
Fetch an XBlock from Learning Core data models.
Fetch an XBlock from openedx_content data models.
This method will find the OLX for the content in Learning Core, parse it
This method will find the OLX for the content in openedx_content, parse it
into an XBlock (with mixins) instance, and properly initialize our
internal LearningCoreFieldData instance with the field values from the
internal OpenedXContentFieldData instance with the field values from the
parsed OLX.
"""
# We can do this more efficiently in a single query later, but for now
@@ -268,7 +268,7 @@ class LearningCoreXBlockRuntime(XBlockRuntime):
def save_block(self, block):
"""
Save any pending field data values to Learning Core data models.
Save any pending field data values to openedx_content data models.
This gets called by block.save() - do not call this directly.
"""
@@ -290,7 +290,7 @@ class LearningCoreXBlockRuntime(XBlockRuntime):
log.warning("User %s does not have permission to edit %s", self.user.username, block.scope_ids.usage_id)
raise RuntimeError("You do not have permission to edit this XBlock")
serialized = serialize_modulestore_block_for_learning_core(block)
serialized = serialize_modulestore_block_for_openedx_content(block)
now = datetime.now(tz=timezone.utc)
usage_key = block.scope_ids.usage_id
with atomic():
@@ -344,7 +344,7 @@ class LearningCoreXBlockRuntime(XBlockRuntime):
def get_component_version_from_block(self, block):
"""
Given an XBlock instance, return the Learning Core ComponentVersion.
Given an XBlock instance, return the openedx_content ComponentVersion.
This relies on our runtime setting the _runtime_requested_version
attribute on blocks that it fetches.
@@ -401,20 +401,20 @@ class LearningCoreXBlockRuntime(XBlockRuntime):
leading "static/" part because it assumes that all files will exist in a
shared, flat namespace (i.e. a course's Files and Uploads).
Learning Core treats assets differently. Each Component has its own,
openedx_content treats assets differently. Each Component has its own,
isolated namespace for asset storage. Furthermore, that namespace
contains content that are not meant to be downloadable, like the
block.xml (the OLX of the Component). There may one day be other files
that are not meant to be externally downloadable there as well, like
Markdown or LaTeX source files or grader code.
By convention, the static assets that we store in Learning Core and are
By convention, the static assets that we store in openedx_content and are
meant for download sit inside a static/ directory that is local to each
Component (and actually separate for each Component Version).
So the transformation looks like this:
1. The Learning Core ComponentVersion has an asset stored as
1. The openedx_content ComponentVersion has an asset stored as
``static/test.png`` in the database.
2. The original OLX content we store references ``/static/test.png``,
per OLX convention. Note the leading "/".

View File

@@ -85,6 +85,9 @@ class XBlockRuntime(RuntimeShim, Runtime):
The main reason we cannot make the runtime a long-lived singleton is that
the XBlock runtime API requires 'user_id' to be a property of the runtime,
not an argument passed in when loading particular blocks.
TODO: This should probably be merged with OpenedXContentRuntime, its one and
only child class. See https://github.com/openedx/openedx-platform/issues/38021
"""
# ** Do not add any XModule compatibility code to this class **
@@ -259,14 +262,14 @@ class XBlockRuntime(RuntimeShim, Runtime):
def parse_xml_file(self, fileobj):
# Deny access to the inherited method
raise NotImplementedError("XML Serialization is only supported with LearningCoreXBlockRuntime")
raise NotImplementedError("XML Serialization is only supported with OpenedXContentRuntime")
def add_node_as_child(self, block, node):
"""
Called by XBlock.parse_xml to treat a child node as a child block.
"""
# Deny access to the inherited method
raise NotImplementedError("XML Serialization is only supported with LearningCoreXBlockRuntime")
raise NotImplementedError("XML Serialization is only supported with OpenedXContentRuntime")
def service(self, block: XBlock, service_name: str):
"""
@@ -301,7 +304,7 @@ class XBlockRuntime(RuntimeShim, Runtime):
return DjangoXBlockUserService(
self.user,
# The value should be updated to whether the user is staff in the context when Learning Core runtime
# The value should be updated to whether the user is staff in the context when openedx_content runtime
# adds support for courses.
user_is_staff=self.user.is_staff, # type: ignore
anonymous_user_id=self.anonymous_student_id,

View File

@@ -102,7 +102,7 @@ class RuntimeShim:
Only used for capa problems.
"""
# TODO: load the python code from Learning Core. Ensure it's not publicly accessible.
# TODO: load the python code from openedx_content. Ensure it's not publicly accessible.
return None
@property

View File

@@ -1,4 +1,4 @@
# .coveragerc for Open edX core lib
# .coveragerc for openedx/core/lib
[run]
data_file = reports/openedx/core/lib/.coverage
source = openedx/core/lib
@@ -8,7 +8,7 @@ parallel = true
ignore_errors = True
[html]
title = Open edX Core Lib Python Test Coverage Report
title = openedx/core/lib Python Test Coverage Report
directory = reports/openedx/core/lib/cover
[xml]

View File

@@ -17,17 +17,17 @@ def serialize_xblock_to_olx(block):
return XBlockSerializer(block)
def serialize_modulestore_block_for_learning_core(block):
def serialize_modulestore_block_for_openedx_content(block):
"""
This class will serialize an XBlock, producing:
(1) A new definition ID for use in Learning Core
(1) A new definition ID for use in openedx_content
(2) an XML string defining the XBlock and referencing the IDs of its
children using <xblock-include /> syntax (which doesn't actually
contain the OLX of its children, just refers to them, so you have to
separately serialize them.)
(3) a list of any static files required by the XBlock and their URL
TODO: We should deprecate this in favor of a new Learning Core implementation.
TODO: We should deprecate this in favor of a new openedx_content implementation.
We've left it as-is for now partly because there are bigger questions that
we have around how we should rewrite this (e.g. are we going to
remove <xblock-include>?).

View File

@@ -49,8 +49,7 @@ class XBlockSerializer:
runtime_supports_explicit_assets = hasattr(block.runtime, 'get_block_assets')
if runtime_supports_explicit_assets:
# If a block supports explicitly tracked assets, things are simple.
# Learning Core backed content supports this, which currently means
# v2 Content Libraries.
# openedx_content (v2 Content Libraries) currently supports this.
self.static_files.extend(
block.runtime.get_block_assets(block, fetch_asset_data)
)

View File

@@ -140,17 +140,17 @@ class XBlockSerializationTestCase(SharedModuleStoreTestCase):
),
])
def test_html_with_static_asset_learning_core(self):
def test_html_with_static_asset_openedx_content(self):
"""
Test the learning-core-specific serialization of an HTML block
Test the openedx_content-specific serialization of an HTML block
"""
block_id = self.course.id.make_usage_key('html', 'just_img') # see sample_courses.py
html_block = modulestore().get_item(block_id)
serialized = api.serialize_xblock_to_olx(html_block)
serialized_learning_core = api.serialize_modulestore_block_for_learning_core(html_block)
serialized_openedx_content = api.serialize_modulestore_block_for_openedx_content(html_block)
self.assertXmlEqual(
serialized_learning_core.olx_str,
# For learning core, OLX should never contain "url_name" as that ID
serialized_openedx_content.olx_str,
# For openedx_content, OLX should never contain "url_name" as that ID
# is specified by the Component key:
"""
<html display_name="Text"><![CDATA[
@@ -160,7 +160,7 @@ class XBlockSerializationTestCase(SharedModuleStoreTestCase):
)
self.assertIn("CDATA", serialized.olx_str)
# Static files should be identical:
self.assertEqual(serialized.static_files, serialized_learning_core.static_files)
self.assertEqual(serialized.static_files, serialized_openedx_content.static_files)
def test_html_with_fields(self):
""" Test an HTML Block with non-default fields like editor='raw' """

View File

@@ -225,17 +225,18 @@ def override_export_fs(block):
XmlMixin.export_to_file = old_global_export_to_file
def learning_core_def_key_from_modulestore_usage_key(usage_key):
def openedx_core_def_key_from_modulestore_usage_key(usage_key):
"""
In modulestore, the "definition key" is a MongoDB ObjectID kept in split's
definitions table, which theoretically allows the same block to be used in
many places (each with a unique usage key). However, that functionality is
not exposed in Studio (other than via content libraries). So when we import
into learning core, we assume that each usage is unique, don't generate a usage
key, and create a new "definition key" from the original usage key.
into the OeX core content API, we assume that each usage is unique, don't
generate a usage key, and create a new "definition key" from the original
usage key.
So modulestore usage key
block-v1:A+B+C+type@html+block@introduction
will become learning core definition key
will become openedx_content definition key
html/introduction
"""
block_type = usage_key.block_type

View File

@@ -63,7 +63,7 @@ numpy<2.0.0
# Date: 2023-09-18
# pinning this version to avoid updates while the library is being developed
# Issue for unpinning: https://github.com/openedx/edx-platform/issues/35269
openedx-learning==0.32.0
openedx-core==0.34.1
# Date: 2023-11-29
# Open AI version 1.0.0 dropped support for openai.ChatCompletion which is currently in use in enterprise.

View File

@@ -41,8 +41,8 @@ attrs==25.4.0
# jsonschema
# lti-consumer-xblock
# openedx-authz
# openedx-core
# openedx-events
# openedx-learning
# referencing
babel==2.17.0
# via
@@ -102,7 +102,7 @@ celery==5.6.2
# edx-enterprise
# enterprise-integrated-channels
# event-tracking
# openedx-learning
# openedx-core
certifi==2026.1.4
# via
# elasticsearch
@@ -231,12 +231,12 @@ django==5.2.11
# jsonfield
# lti-consumer-xblock
# openedx-authz
# openedx-core
# openedx-django-pyfs
# openedx-django-wiki
# openedx-events
# openedx-filters
# openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
# super-csv
@@ -388,8 +388,8 @@ djangorestframework==3.16.1
# edx-proctoring
# edx-submissions
# openedx-authz
# openedx-core
# openedx-forum
# openedx-learning
# ora2
# super-csv
djangorestframework-xml==2.0.0
@@ -469,7 +469,7 @@ edx-drf-extensions==10.6.0
# edxval
# enterprise-integrated-channels
# openedx-authz
# openedx-learning
# openedx-core
edx-enterprise==6.6.3
# via
# -c requirements/constraints.txt
@@ -808,6 +808,10 @@ openedx-authz==0.20.0
# via -r requirements/edx/kernel.in
openedx-calc==4.0.3
# via -r requirements/edx/kernel.in
openedx-core==0.34.1
# via
# -c requirements/constraints.txt
# -r requirements/edx/kernel.in
openedx-django-pyfs==3.8.0
# via
# lti-consumer-xblock
@@ -832,10 +836,6 @@ openedx-filters==2.1.0
# ora2
openedx-forum==0.4.0
# via -r requirements/edx/kernel.in
openedx-learning==0.32.0
# via
# -c requirements/constraints.txt
# -r requirements/edx/kernel.in
optimizely-sdk==5.4.0
# via -r requirements/edx/bundled.in
ora2==6.17.2
@@ -1072,7 +1072,7 @@ rules==3.5
# -r requirements/edx/kernel.in
# edx-enterprise
# edx-proctoring
# openedx-learning
# openedx-core
s3transfer==0.16.0
# via boto3
sailthru-client==2.2.3
@@ -1165,7 +1165,7 @@ tinycss2==1.4.0
# via bleach
tomlkit==0.14.0
# via
# openedx-learning
# openedx-core
# snowflake-connector-python
tqdm==4.67.1
# via nltk

View File

@@ -94,8 +94,8 @@ attrs==25.4.0
# jsonschema
# lti-consumer-xblock
# openedx-authz
# openedx-core
# openedx-events
# openedx-learning
# referencing
babel==2.17.0
# via
@@ -197,7 +197,7 @@ celery==5.6.2
# edx-enterprise
# enterprise-integrated-channels
# event-tracking
# openedx-learning
# openedx-core
certifi==2026.1.4
# via
# -r requirements/edx/doc.txt
@@ -407,12 +407,12 @@ django==5.2.11
# jsonfield
# lti-consumer-xblock
# openedx-authz
# openedx-core
# openedx-django-pyfs
# openedx-django-wiki
# openedx-events
# openedx-filters
# openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
# super-csv
@@ -630,8 +630,8 @@ djangorestframework==3.16.1
# edx-proctoring
# edx-submissions
# openedx-authz
# openedx-core
# openedx-forum
# openedx-learning
# ora2
# super-csv
djangorestframework-stubs==3.16.7
@@ -751,7 +751,7 @@ edx-drf-extensions==10.6.0
# edxval
# enterprise-integrated-channels
# openedx-authz
# openedx-learning
# openedx-core
edx-enterprise==6.6.3
# via
# -c requirements/constraints.txt
@@ -1365,6 +1365,11 @@ openedx-calc==4.0.3
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
openedx-core==0.34.1
# via
# -c requirements/constraints.txt
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
openedx-django-pyfs==3.8.0
# via
# -r requirements/edx/doc.txt
@@ -1399,11 +1404,6 @@ openedx-forum==0.4.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
openedx-learning==0.32.0
# via
# -c requirements/constraints.txt
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
optimizely-sdk==5.4.0
# via
# -r requirements/edx/doc.txt
@@ -1881,7 +1881,7 @@ rules==3.5
# -r requirements/edx/testing.txt
# edx-enterprise
# edx-proctoring
# openedx-learning
# openedx-core
s3transfer==0.16.0
# via
# -r requirements/edx/doc.txt
@@ -2107,7 +2107,7 @@ tomlkit==0.14.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# openedx-learning
# openedx-core
# pylint
# snowflake-connector-python
tox==4.34.1

View File

@@ -65,8 +65,8 @@ attrs==25.4.0
# jsonschema
# lti-consumer-xblock
# openedx-authz
# openedx-core
# openedx-events
# openedx-learning
# referencing
babel==2.17.0
# via
@@ -147,7 +147,7 @@ celery==5.6.2
# edx-enterprise
# enterprise-integrated-channels
# event-tracking
# openedx-learning
# openedx-core
certifi==2026.1.4
# via
# -r requirements/edx/base.txt
@@ -294,12 +294,12 @@ django==5.2.11
# jsonfield
# lti-consumer-xblock
# openedx-authz
# openedx-core
# openedx-django-pyfs
# openedx-django-wiki
# openedx-events
# openedx-filters
# openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
# super-csv
@@ -465,8 +465,8 @@ djangorestframework==3.16.1
# edx-proctoring
# edx-submissions
# openedx-authz
# openedx-core
# openedx-forum
# openedx-learning
# ora2
# super-csv
djangorestframework-xml==2.0.0
@@ -558,7 +558,7 @@ edx-drf-extensions==10.6.0
# edxval
# enterprise-integrated-channels
# openedx-authz
# openedx-learning
# openedx-core
edx-enterprise==6.6.3
# via
# -c requirements/constraints.txt
@@ -984,6 +984,10 @@ openedx-authz==0.20.0
# via -r requirements/edx/base.txt
openedx-calc==4.0.3
# via -r requirements/edx/base.txt
openedx-core==0.34.1
# via
# -c requirements/constraints.txt
# -r requirements/edx/base.txt
openedx-django-pyfs==3.8.0
# via
# -r requirements/edx/base.txt
@@ -1009,10 +1013,6 @@ openedx-filters==2.1.0
# ora2
openedx-forum==0.4.0
# via -r requirements/edx/base.txt
openedx-learning==0.32.0
# via
# -c requirements/constraints.txt
# -r requirements/edx/base.txt
optimizely-sdk==5.4.0
# via -r requirements/edx/base.txt
ora2==6.17.2
@@ -1312,7 +1312,7 @@ rules==3.5
# -r requirements/edx/base.txt
# edx-enterprise
# edx-proctoring
# openedx-learning
# openedx-core
s3transfer==0.16.0
# via
# -r requirements/edx/base.txt
@@ -1480,7 +1480,7 @@ tinycss2==1.4.0
tomlkit==0.14.0
# via
# -r requirements/edx/base.txt
# openedx-learning
# openedx-core
# snowflake-connector-python
tqdm==4.67.1
# via

View File

@@ -113,11 +113,11 @@ oauthlib # OAuth specification support for authentica
olxcleaner
openedx-atlas # CLI tool to manage translations
openedx-calc # Library supporting mathematical calculations for Open edX
openedx-core # Open edX Core: Content, Tagging, and other foundational APIs
openedx-django-require
openedx-events # Open edX Events from Hooks Extension Framework (OEP-50)
openedx-filters # Open edX Filters from Hooks Extension Framework (OEP-50)
openedx-forum # Open edX forum v2 application
openedx-learning # Open edX Learning core (experimental)
openedx-django-wiki
path
piexif # Exif image metadata manipulation, used in the profile_images app

View File

@@ -66,8 +66,8 @@ attrs==25.4.0
# jsonschema
# lti-consumer-xblock
# openedx-authz
# openedx-core
# openedx-events
# openedx-learning
# referencing
babel==2.17.0
# via
@@ -147,7 +147,7 @@ celery==5.6.2
# edx-enterprise
# enterprise-integrated-channels
# event-tracking
# openedx-learning
# openedx-core
certifi==2026.1.4
# via
# -r requirements/edx/base.txt
@@ -321,12 +321,12 @@ django==5.2.11
# jsonfield
# lti-consumer-xblock
# openedx-authz
# openedx-core
# openedx-django-pyfs
# openedx-django-wiki
# openedx-events
# openedx-filters
# openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
# super-csv
@@ -492,8 +492,8 @@ djangorestframework==3.16.1
# edx-proctoring
# edx-submissions
# openedx-authz
# openedx-core
# openedx-forum
# openedx-learning
# ora2
# super-csv
djangorestframework-xml==2.0.0
@@ -580,7 +580,7 @@ edx-drf-extensions==10.6.0
# edxval
# enterprise-integrated-channels
# openedx-authz
# openedx-learning
# openedx-core
edx-enterprise==6.6.3
# via
# -c requirements/constraints.txt
@@ -1034,6 +1034,10 @@ openedx-authz==0.20.0
# via -r requirements/edx/base.txt
openedx-calc==4.0.3
# via -r requirements/edx/base.txt
openedx-core==0.34.1
# via
# -c requirements/constraints.txt
# -r requirements/edx/base.txt
openedx-django-pyfs==3.8.0
# via
# -r requirements/edx/base.txt
@@ -1059,10 +1063,6 @@ openedx-filters==2.1.0
# ora2
openedx-forum==0.4.0
# via -r requirements/edx/base.txt
openedx-learning==0.32.0
# via
# -c requirements/constraints.txt
# -r requirements/edx/base.txt
optimizely-sdk==5.4.0
# via -r requirements/edx/base.txt
ora2==6.17.2
@@ -1429,7 +1429,7 @@ rules==3.5
# -r requirements/edx/base.txt
# edx-enterprise
# edx-proctoring
# openedx-learning
# openedx-core
s3transfer==0.16.0
# via
# -r requirements/edx/base.txt
@@ -1557,7 +1557,7 @@ tinycss2==1.4.0
tomlkit==0.14.0
# via
# -r requirements/edx/base.txt
# openedx-learning
# openedx-core
# pylint
# snowflake-connector-python
tox==4.34.1

View File

@@ -41,16 +41,16 @@ Direction
Currently, this directory contains a lot of mission-critical functionality, so continued maintenance and simplification of it is important.
Still, we aim to eventually dissolve the directory in favor of more focused & decoupled subsystems:
* ModuleStore is superseded by the `Learning Core`_ storage backend.
* Learning Core-backend content is rendered by a new, simplified `edx-platform XBlock runtime`_.
* Navigation, partitioning, and composition of learning content is being re-architected in the `openedx-learning`_ library.
* ModuleStore is superseded by the `openedx_content`_ storage backend.
* Content within ``openedx_content`` is rendered by a new, simplified `openedx-platform XBlock runtime`_.
* Navigation, partitioning, and composition of learning content is being re-architected in the `openedx-core`_ library,
which includes the implementations of ``openedx_content`` and ``openedx_tagging``.
* All new XBlocks are implemented in separate repositories, such as `xblock-drag-and-drop-v2`_.
To help with this direction, please **do not add new functionality to this directory**. If you feel that you need to add code to this directory, reach out on `the forums`_; it's likely that someone can help you find a different way to implement your change that will be more robust and architecturally sound!
.. _Learning Core: https://github.com/openedx/openedx-learning/
.. _edx-platform XBlock runtime: https://github.com/openedx/edx-platform/tree/master/openedx/core/djangoapps/xblock
.. _openedx-learning: https://github.com/openedx/openedx-learning
.. _openedx_content: https://github.com/openedx/openedx-core/tree/main/src/openedx_content
.. _openedx-platform XBlock runtime: https://github.com/openedx/openedx-platform/tree/master/openedx/core/djangoapps/xblock
.. _openedx-core: https://github.com/openedx/openedx-core
.. _xblock-drag-and-drop-v2: https://github.com/openedx/xblock-drag-and-drop-v2
.. _the forums: https://discuss.openedx.org

View File

@@ -297,7 +297,7 @@ class _BuiltinHtmlBlockMixin( # lint-amnesty, pylint: disable=abstract-method
@classmethod
def parse_xml_new_runtime(cls, node, runtime, keys):
"""
Parse XML in the new learning-core-based runtime. Since it doesn't yet
Parse XML in the new openedx_content-based runtime. Since it doesn't yet
support loading separate .html files, the HTML data is assumed to be in
a CDATA child or otherwise just inline in the OLX.
"""

View File

@@ -3,7 +3,7 @@ LegacyLibraryContent: The XBlock used to randomly select a subset of blocks from
In Studio, it's called the "Randomized Content Module".
In the long-term, this block is deprecated in favor of "v2" (learning core-backed) library references:
In the long-term, this block is deprecated in favor of "v2" (openedx_content-backed) library references:
https://github.com/openedx/edx-platform/issues/32457
We need to retain backwards-compatibility, but please do not build any new features into this.

View File

@@ -24,7 +24,7 @@ class LegacyLibraryToolsService:
"""
Service for LegacyLibraryContentBlock.
Allows to interact with libraries in the modulestore and learning core.
Allows to interact with libraries in the modulestore and openedx_content.
Should only be used in the CMS.
"""

View File

@@ -66,7 +66,7 @@ class RawMixin:
Interpret the parsed XML in `node`, creating a new instance of this
module.
"""
# In the new/learning-core-based runtime, XModule parsing (from
# In the new/openedx_content-based runtime, XModule parsing (from
# XmlMixin) is disabled, so definition_from_xml will not be
# called, and instead the "normal" XBlock parse_xml will be used.
# However, it's not compatible with RawMixin, so we implement

View File

@@ -357,7 +357,7 @@ class VideoStudentViewHandlers:
def yt_video_metadata(self, request, suffix=''): # lint-amnesty, pylint: disable=unused-argument
"""
Endpoint to get YouTube metadata.
This handler is only used in the Learning-Core-based runtime. The old
This handler is only used in the openedx_content-based runtime. The old
runtime uses a similar REST API that's not an XBlock handler.
"""
from lms.djangoapps.courseware.views.views import load_metadata_from_youtube

View File

@@ -422,7 +422,7 @@ class XmlMixin:
@classmethod
def parse_xml_new_runtime(cls, node, runtime, keys):
"""
This XML lives within Learning Core and the new runtime doesn't need this
This XML lives within openedx-core and the new runtime doesn't need this
legacy XModule code. Use the "normal" XBlock parsing code.
"""
try: