refactor: update to use Learning Core's new public API
This also bumps our openedx-learning dependency to 0.10.0 (the first version with the new openedx_learning.api package).
This commit is contained in:
@@ -1881,9 +1881,9 @@ INSTALLED_APPS = [
|
||||
'openedx_events',
|
||||
|
||||
# Learning Core Apps, used by v2 content libraries (content_libraries app)
|
||||
"openedx_learning.core.components",
|
||||
"openedx_learning.core.contents",
|
||||
"openedx_learning.core.publishing",
|
||||
"openedx_learning.apps.authoring.components",
|
||||
"openedx_learning.apps.authoring.contents",
|
||||
"openedx_learning.apps.authoring.publishing",
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -3385,9 +3385,9 @@ INSTALLED_APPS = [
|
||||
'openedx_events',
|
||||
|
||||
# Learning Core Apps, used by v2 content libraries (content_libraries app)
|
||||
"openedx_learning.core.components",
|
||||
"openedx_learning.core.contents",
|
||||
"openedx_learning.core.publishing",
|
||||
"openedx_learning.apps.authoring.components",
|
||||
"openedx_learning.apps.authoring.contents",
|
||||
"openedx_learning.apps.authoring.publishing",
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -85,10 +85,8 @@ from openedx_events.content_authoring.signals import (
|
||||
LIBRARY_BLOCK_DELETED,
|
||||
LIBRARY_BLOCK_UPDATED,
|
||||
)
|
||||
from openedx_learning.core.publishing import api as publishing_api
|
||||
from openedx_learning.core.contents import api as contents_api
|
||||
from openedx_learning.core.components import api as components_api
|
||||
from openedx_learning.core.components.models import Component
|
||||
from openedx_learning.api import authoring as authoring_api
|
||||
from openedx_learning.api.authoring_models import Component, MediaType
|
||||
from organizations.models import Organization
|
||||
from xblock.core import XBlock
|
||||
from xblock.exceptions import XBlockNotFoundError
|
||||
@@ -327,18 +325,18 @@ def get_library(library_key):
|
||||
"""
|
||||
ref = ContentLibrary.objects.get_by_key(library_key)
|
||||
learning_package = ref.learning_package
|
||||
num_blocks = publishing_api.get_all_drafts(learning_package.id).count()
|
||||
last_publish_log = publishing_api.get_last_publish(learning_package.id)
|
||||
has_unpublished_changes = publishing_api.get_entities_with_unpublished_changes(learning_package.id) \
|
||||
.exists()
|
||||
num_blocks = authoring_api.get_all_drafts(learning_package.id).count()
|
||||
last_publish_log = authoring_api.get_last_publish(learning_package.id)
|
||||
has_unpublished_changes = authoring_api.get_entities_with_unpublished_changes(learning_package.id) \
|
||||
.exists()
|
||||
|
||||
# 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,
|
||||
# and has_unpublished_changes should be sufficient.
|
||||
# Ref: https://github.com/openedx/edx-platform/issues/34283
|
||||
has_unpublished_deletes = publishing_api.get_entities_with_unpublished_deletes(learning_package.id) \
|
||||
.exists()
|
||||
has_unpublished_deletes = authoring_api.get_entities_with_unpublished_deletes(learning_package.id) \
|
||||
.exists()
|
||||
|
||||
# Learning Core doesn't really have a notion of a global version number,but
|
||||
# we can sort of approximate it by using the primary key of the last publish
|
||||
@@ -415,7 +413,7 @@ def create_library(
|
||||
allow_public_read=allow_public_read,
|
||||
license=library_license,
|
||||
)
|
||||
learning_package = publishing_api.create_learning_package(
|
||||
learning_package = authoring_api.create_learning_package(
|
||||
key=str(ref.library_key),
|
||||
title=title,
|
||||
description=description,
|
||||
@@ -556,7 +554,7 @@ def update_library(
|
||||
content_lib.save()
|
||||
|
||||
if learning_pkg_changed:
|
||||
publishing_api.update_learning_package(
|
||||
authoring_api.update_learning_package(
|
||||
content_lib.learning_package_id,
|
||||
title=title,
|
||||
description=description,
|
||||
@@ -614,7 +612,7 @@ def get_library_components(library_key, text_search=None, block_types=None) -> Q
|
||||
"""
|
||||
lib = ContentLibrary.objects.get_by_key(library_key) # type: ignore[attr-defined]
|
||||
learning_package = lib.learning_package
|
||||
components = components_api.get_components(
|
||||
components = authoring_api.get_components(
|
||||
learning_package.id,
|
||||
draft=True,
|
||||
namespace='xblock.v1',
|
||||
@@ -693,13 +691,13 @@ def set_library_block_olx(usage_key, new_olx_str):
|
||||
now = datetime.now(tz=timezone.utc)
|
||||
|
||||
with transaction.atomic():
|
||||
new_content = contents_api.get_or_create_text_content(
|
||||
new_content = authoring_api.get_or_create_text_content(
|
||||
component.learning_package_id,
|
||||
get_or_create_olx_media_type(usage_key.block_type).id,
|
||||
text=new_olx_str,
|
||||
created=now,
|
||||
)
|
||||
components_api.create_next_version(
|
||||
authoring_api.create_next_version(
|
||||
component.pk,
|
||||
title=new_title,
|
||||
content_to_replace={
|
||||
@@ -736,7 +734,7 @@ def create_library_block(library_key, block_type, definition_id):
|
||||
)
|
||||
|
||||
# If adding a component would take us over our max, return an error.
|
||||
component_count = publishing_api.get_all_drafts(ref.learning_package.id).count()
|
||||
component_count = authoring_api.get_all_drafts(ref.learning_package.id).count()
|
||||
if component_count + 1 > settings.MAX_BLOCKS_PER_CONTENT_LIBRARY:
|
||||
raise BlockLimitReachedError(
|
||||
_("Library cannot have more than {} Components").format(
|
||||
@@ -785,14 +783,14 @@ def _component_exists(usage_key: UsageKeyV2) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def get_or_create_olx_media_type(block_type: str) -> contents_api.MediaType:
|
||||
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
|
||||
OLX, we use the "application/vnd.*" convention, per RFC 6838.
|
||||
"""
|
||||
return contents_api.get_or_create_media_type(
|
||||
return authoring_api.get_or_create_media_type(
|
||||
f"application/vnd.openedx.xblock.v1.{block_type}+xml"
|
||||
)
|
||||
|
||||
@@ -819,10 +817,10 @@ def _create_component_for_block(content_lib, usage_key):
|
||||
learning_package = content_lib.learning_package
|
||||
|
||||
with transaction.atomic():
|
||||
component_type = components_api.get_or_create_component_type(
|
||||
component_type = authoring_api.get_or_create_component_type(
|
||||
"xblock.v1", usage_key.block_type
|
||||
)
|
||||
component, component_version = components_api.create_component_and_version(
|
||||
component, component_version = authoring_api.create_component_and_version(
|
||||
learning_package.id,
|
||||
component_type=component_type,
|
||||
local_key=usage_key.block_id,
|
||||
@@ -830,13 +828,13 @@ def _create_component_for_block(content_lib, usage_key):
|
||||
created=now,
|
||||
created_by=None,
|
||||
)
|
||||
content = contents_api.get_or_create_text_content(
|
||||
content = authoring_api.get_or_create_text_content(
|
||||
learning_package.id,
|
||||
get_or_create_olx_media_type(usage_key.block_type).id,
|
||||
text=xml_text,
|
||||
created=now,
|
||||
)
|
||||
components_api.create_component_version_content(
|
||||
authoring_api.create_component_version_content(
|
||||
component_version.pk,
|
||||
content.id,
|
||||
key="block.xml",
|
||||
@@ -849,7 +847,7 @@ def delete_library_block(usage_key, remove_from_parent=True):
|
||||
Delete the specified block from this library (soft delete).
|
||||
"""
|
||||
component = get_component_from_usage_key(usage_key)
|
||||
publishing_api.soft_delete_draft(component.pk)
|
||||
authoring_api.soft_delete_draft(component.pk)
|
||||
|
||||
LIBRARY_BLOCK_DELETED.send_event(
|
||||
library_block=LibraryBlockData(
|
||||
@@ -938,7 +936,7 @@ def publish_changes(library_key):
|
||||
"""
|
||||
learning_package = ContentLibrary.objects.get_by_key(library_key).learning_package
|
||||
|
||||
publishing_api.publish_all_drafts(learning_package.id)
|
||||
authoring_api.publish_all_drafts(learning_package.id)
|
||||
|
||||
CONTENT_LIBRARY_UPDATED.send_event(
|
||||
content_library=ContentLibraryData(
|
||||
@@ -954,7 +952,7 @@ def revert_changes(library_key):
|
||||
last published version.
|
||||
"""
|
||||
learning_package = ContentLibrary.objects.get_by_key(library_key).learning_package
|
||||
publishing_api.reset_drafts_to_published(learning_package.id)
|
||||
authoring_api.reset_drafts_to_published(learning_package.id)
|
||||
|
||||
CONTENT_LIBRARY_UPDATED.send_event(
|
||||
content_library=ContentLibraryData(
|
||||
|
||||
@@ -10,7 +10,7 @@ from openedx.core.djangoapps.content_libraries import api, permissions
|
||||
from openedx.core.djangoapps.content_libraries.models import ContentLibrary
|
||||
from openedx.core.djangoapps.xblock.api import LearningContext
|
||||
|
||||
from openedx_learning.core.components import api as components_api
|
||||
from openedx_learning.api import authoring as authoring_api
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -87,7 +87,7 @@ class LibraryContextImpl(LearningContext):
|
||||
if learning_package is None:
|
||||
return False
|
||||
|
||||
return components_api.component_exists_by_key(
|
||||
return authoring_api.component_exists_by_key(
|
||||
learning_package.id,
|
||||
namespace='xblock.v1',
|
||||
type_name=usage_key.block_type,
|
||||
|
||||
@@ -57,7 +57,7 @@ from openedx.core.djangoapps.content_libraries.constants import (
|
||||
LIBRARY_TYPES, COMPLEX, LICENSE_OPTIONS,
|
||||
ALL_RIGHTS_RESERVED,
|
||||
)
|
||||
from openedx_learning.core.publishing.models import LearningPackage
|
||||
from openedx_learning.api.authoring_models import LearningPackage
|
||||
from organizations.models import Organization # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
from .apps import ContentLibrariesConfig
|
||||
|
||||
@@ -15,12 +15,10 @@ import threading
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from openedx_learning.core.components import api as components_api
|
||||
from openedx_learning.core.components.models import Component
|
||||
from openedx_learning.core.publishing import api as publishing_api
|
||||
from openedx_learning.api import authoring as authoring_api
|
||||
from openedx_learning.api.authoring_models import Component
|
||||
from opaque_keys.edx.keys import UsageKeyV2
|
||||
from opaque_keys.edx.locator import BundleDefinitionLocator, LibraryUsageLocatorV2
|
||||
|
||||
from rest_framework.exceptions import NotFound
|
||||
from xblock.core import XBlock
|
||||
from xblock.exceptions import NoSuchViewError
|
||||
@@ -28,13 +26,10 @@ from xblock.plugin import PluginMissingError
|
||||
|
||||
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.runtime import XBlockRuntimeSystem as _XBlockRuntimeSystem
|
||||
from .utils import get_secure_token_for_xblock_handler, get_xblock_id_for_anonymous_user
|
||||
|
||||
@@ -192,10 +187,10 @@ def get_component_from_usage_key(usage_key: UsageKeyV2) -> Component:
|
||||
This is a lower-level function that will return a Component even if there is
|
||||
no current draft version of that Component (because it's been soft-deleted).
|
||||
"""
|
||||
learning_package = publishing_api.get_learning_package_by_key(
|
||||
learning_package = authoring_api.get_learning_package_by_key(
|
||||
str(usage_key.context_key)
|
||||
)
|
||||
return components_api.get_component_by_key(
|
||||
return authoring_api.get_component_by_key(
|
||||
learning_package.id,
|
||||
namespace='xblock.v1',
|
||||
type_name=usage_key.block_type,
|
||||
|
||||
@@ -10,9 +10,7 @@ from datetime import datetime, timezone
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.transaction import atomic
|
||||
|
||||
from openedx_learning.core.components import api as components_api
|
||||
from openedx_learning.core.contents import api as contents_api
|
||||
from openedx_learning.core.publishing import api as publishing_api
|
||||
from openedx_learning.api import authoring as authoring_api
|
||||
|
||||
from lxml import etree
|
||||
|
||||
@@ -239,16 +237,16 @@ class LearningCoreXBlockRuntime(XBlockRuntime):
|
||||
usage_key = block.scope_ids.usage_id
|
||||
with atomic():
|
||||
component = self._get_component_from_usage_key(usage_key)
|
||||
block_media_type = contents_api.get_or_create_media_type(
|
||||
block_media_type = authoring_api.get_or_create_media_type(
|
||||
f"application/vnd.openedx.xblock.v1.{usage_key.block_type}+xml"
|
||||
)
|
||||
content = contents_api.get_or_create_text_content(
|
||||
content = authoring_api.get_or_create_text_content(
|
||||
component.learning_package_id,
|
||||
block_media_type.id,
|
||||
text=serialized.olx_str,
|
||||
created=now,
|
||||
)
|
||||
components_api.create_next_version(
|
||||
authoring_api.create_next_version(
|
||||
component.pk,
|
||||
title=block.display_name,
|
||||
content_to_replace={
|
||||
@@ -267,9 +265,9 @@ class LearningCoreXBlockRuntime(XBlockRuntime):
|
||||
TODO: This is the third place where we're implementing this. Figure out
|
||||
where the definitive place should be and have everything else call that.
|
||||
"""
|
||||
learning_package = publishing_api.get_learning_package_by_key(str(usage_key.lib_key))
|
||||
learning_package = authoring_api.get_learning_package_by_key(str(usage_key.lib_key))
|
||||
try:
|
||||
component = components_api.get_component_by_key(
|
||||
component = authoring_api.get_component_by_key(
|
||||
learning_package.id,
|
||||
namespace='xblock.v1',
|
||||
type_name=usage_key.block_type,
|
||||
|
||||
@@ -97,7 +97,7 @@ libsass==0.10.0
|
||||
click==8.1.6
|
||||
|
||||
# pinning this version to avoid updates while the library is being developed
|
||||
openedx-learning==0.9.4
|
||||
openedx-learning==0.10.0
|
||||
|
||||
# Open AI version 1.0.0 dropped support for openai.ChatCompletion which is currently in use in enterprise.
|
||||
openai<=0.28.1
|
||||
|
||||
@@ -775,7 +775,7 @@ openedx-filters==1.8.1
|
||||
# -r requirements/edx/kernel.in
|
||||
# lti-consumer-xblock
|
||||
# ora2
|
||||
openedx-learning==0.9.4
|
||||
openedx-learning==0.10.0
|
||||
# via
|
||||
# -c requirements/edx/../constraints.txt
|
||||
# -r requirements/edx/kernel.in
|
||||
|
||||
@@ -1331,7 +1331,7 @@ openedx-filters==1.8.1
|
||||
# -r requirements/edx/testing.txt
|
||||
# lti-consumer-xblock
|
||||
# ora2
|
||||
openedx-learning==0.9.4
|
||||
openedx-learning==0.10.0
|
||||
# via
|
||||
# -c requirements/edx/../constraints.txt
|
||||
# -r requirements/edx/doc.txt
|
||||
|
||||
@@ -906,7 +906,7 @@ openedx-filters==1.8.1
|
||||
# -r requirements/edx/base.txt
|
||||
# lti-consumer-xblock
|
||||
# ora2
|
||||
openedx-learning==0.9.4
|
||||
openedx-learning==0.10.0
|
||||
# via
|
||||
# -c requirements/edx/../constraints.txt
|
||||
# -r requirements/edx/base.txt
|
||||
|
||||
@@ -991,7 +991,7 @@ openedx-filters==1.8.1
|
||||
# -r requirements/edx/base.txt
|
||||
# lti-consumer-xblock
|
||||
# ora2
|
||||
openedx-learning==0.9.4
|
||||
openedx-learning==0.10.0
|
||||
# via
|
||||
# -c requirements/edx/../constraints.txt
|
||||
# -r requirements/edx/base.txt
|
||||
|
||||
12
setup.cfg
12
setup.cfg
@@ -62,6 +62,7 @@ root_packages =
|
||||
lms
|
||||
cms
|
||||
openedx
|
||||
openedx_learning
|
||||
include_external_packages = True
|
||||
contract_types =
|
||||
# Our custom contract which checks that we're only importing from 'api.py'
|
||||
@@ -185,3 +186,14 @@ allowed_modules =
|
||||
# Only imports from api.py are allowed elsewhere in the code
|
||||
# See https://open-edx-proposals.readthedocs.io/en/latest/best-practices/oep-0049-django-app-patterns.html#api-py
|
||||
api
|
||||
|
||||
[importlinter:contract:3]
|
||||
name = Do not import apps from openedx-learning (only import from openedx_learning.api.* and openedx_learning.lib.*).
|
||||
type = forbidden
|
||||
source_modules =
|
||||
cms
|
||||
lms
|
||||
openedx
|
||||
forbidden_modules =
|
||||
openedx_learning.apps
|
||||
allow_indirect_imports = True
|
||||
|
||||
Reference in New Issue
Block a user