refactor: bring common settings into common module (#37746)

This commit is contained in:
Taylor Payne
2026-01-09 09:20:59 -07:00
committed by GitHub
parent 7f1f8767a8
commit 7111e8b18c
13 changed files with 789 additions and 1222 deletions

View File

@@ -46,16 +46,13 @@ from datetime import timedelta
from django.utils.translation import gettext_lazy as _
import lms.envs.common
from openedx.envs.common import * # pylint: disable=wildcard-import
from path import Path as path
from lms.djangoapps.lms_xblock.mixin import LmsBlockMixin
from cms.lib.xblock.authoring_mixin import AuthoringMixin
from cms.lib.xblock.upstream_sync import UpstreamSyncMixin
from xmodule.modulestore.edit_info import EditInfoMixin
from xmodule.x_module import ResourceTemplates
from openedx.core.lib.derived import Derived
from openedx.core.lib.features_setting_proxy import FeaturesProxy
@@ -269,117 +266,50 @@ MARKETING_EMAILS_OPT_IN = False
############################# MICROFRONTENDS ###################################
COURSE_AUTHORING_MICROFRONTEND_URL = None
############################# SOCIAL MEDIA SHARING #############################
SOCIAL_SHARING_SETTINGS = {
# Note: Ensure 'CUSTOM_COURSE_URLS' has a matching value in lms/envs/common.py
'CUSTOM_COURSE_URLS': False,
'DASHBOARD_FACEBOOK': False,
'CERTIFICATE_FACEBOOK': False,
'CERTIFICATE_TWITTER': False,
'DASHBOARD_TWITTER': False
}
############################# SET PATH INFORMATION #############################
PROJECT_ROOT = path(__file__).abspath().dirname().dirname() # /edx-platform/cms
REPO_ROOT = PROJECT_ROOT.dirname()
COMMON_ROOT = REPO_ROOT / "common"
OPENEDX_ROOT = REPO_ROOT / "openedx"
CMS_ROOT = REPO_ROOT / "cms"
LMS_ROOT = REPO_ROOT / "lms"
ENV_ROOT = REPO_ROOT.dirname() # virtualenv dir /edx-platform is in
COURSES_ROOT = ENV_ROOT / "data"
XMODULE_ROOT = REPO_ROOT / "xmodule"
GITHUB_REPO_ROOT = ENV_ROOT / "data"
# For geolocation ip database
GEOIP_PATH = REPO_ROOT / "common/static/data/geoip/GeoLite2-Country.mmdb"
DATA_DIR = COURSES_ROOT
######################## BRANCH.IO ###########################
BRANCH_IO_KEY = ''
######################## GOOGLE ANALYTICS ###########################
GOOGLE_ANALYTICS_ACCOUNT = None
######################## HOTJAR ###########################
HOTJAR_ID = 00000
############################# TEMPLATE CONFIGURATION #############################
# Mako templating
import tempfile
MAKO_MODULE_DIR = os.path.join(tempfile.gettempdir(), 'mako_cms')
MAKO_TEMPLATE_DIRS_BASE = [
PROJECT_ROOT / 'templates',
COMMON_ROOT / 'templates',
COMMON_ROOT / 'djangoapps' / 'pipeline_mako' / 'templates',
COMMON_ROOT / 'static', # required to statically include common Underscore templates
OPENEDX_ROOT / 'core' / 'djangoapps' / 'cors_csrf' / 'templates',
OPENEDX_ROOT / 'core' / 'djangoapps' / 'dark_lang' / 'templates',
OPENEDX_ROOT / 'core' / 'lib' / 'license' / 'templates',
CMS_ROOT / 'djangoapps' / 'pipeline_js' / 'templates',
XMODULE_ROOT / 'capa' / 'templates',
]
CONTEXT_PROCESSORS = (
'django.template.context_processors.request',
'django.template.context_processors.static',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.i18n',
'django.contrib.auth.context_processors.auth', # this is required for admin
'django.template.context_processors.csrf',
'help_tokens.context_processor',
'openedx.core.djangoapps.site_configuration.context_processors.configuration_context',
)
MAKO_TEMPLATE_DIRS_BASE.insert(3, COMMON_ROOT / 'static')
MAKO_TEMPLATE_DIRS_BASE.append(CMS_ROOT / 'djangoapps' / 'pipeline_js' / 'templates')
MAKO_TEMPLATE_DIRS_BASE.append(XMODULE_ROOT / 'capa' / 'templates')
# Django templating
TEMPLATES = [
{
'NAME': 'django',
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# Don't look for template source files inside installed applications.
'APP_DIRS': False,
# Instead, look for template source files in these dirs.
'DIRS': Derived(make_mako_template_dirs),
# Options specific to this backend.
'OPTIONS': {
'loaders': (
# We have to use mako-aware template loaders to be able to include
# mako templates inside django templates (such as main_django.html).
'openedx.core.djangoapps.theming.template_loaders.ThemeTemplateLoader',
'common.djangoapps.edxmako.makoloader.MakoFilesystemLoader',
'common.djangoapps.edxmako.makoloader.MakoAppDirectoriesLoader',
),
'context_processors': CONTEXT_PROCESSORS,
# Change 'debug' in your environment settings files - not here.
'debug': False
}
},
{
'NAME': 'mako',
'BACKEND': 'common.djangoapps.edxmako.backend.Mako',
'APP_DIRS': False,
'DIRS': Derived(make_mako_template_dirs),
'OPTIONS': {
'context_processors': CONTEXT_PROCESSORS,
'debug': False,
}
},
def make_lms_template_path(settings):
"""
Make the path for the LMS "templates" dir
"""
templates_path = settings.PROJECT_ROOT / 'templates'
return templates_path.replace('cms', 'lms')
lms_mako_template_dirs_base[0] = Derived(make_lms_template_path)
TEMPLATES[0]['DIRS'] = Derived(make_mako_template_dirs)
TEMPLATES.append(
{
# This separate copy of the Mako backend is used to render previews using the LMS templates
'NAME': 'preview',
'BACKEND': 'common.djangoapps.edxmako.backend.Mako',
'APP_DIRS': False,
'DIRS': lms.envs.common.MAKO_TEMPLATE_DIRS_BASE,
'DIRS': lms_mako_template_dirs_base,
'OPTIONS': {
'context_processors': CONTEXT_PROCESSORS,
'debug': False,
'namespace': 'lms.main',
}
},
]
DEFAULT_TEMPLATE_ENGINE = TEMPLATES[0]
}
)
#################################### AWS #######################################
AWS_SECURITY_TOKEN = None
@@ -387,13 +317,8 @@ AWS_SECURITY_TOKEN = None
##############################################################################
# use the ratelimit backend to prevent brute force attacks
AUTHENTICATION_BACKENDS = [
'auth_backends.backends.EdXOAuth2',
'rules.permissions.ObjectPermissionBackend',
'openedx.core.djangoapps.content_libraries.auth.LtiAuthenticationBackend',
'django.contrib.auth.backends.AllowAllUsersModelBackend',
'bridgekeeper.backends.RulePermissionBackend',
]
AUTHENTICATION_BACKENDS.insert(0, 'auth_backends.backends.EdXOAuth2')
AUTHENTICATION_BACKENDS.insert(2, 'openedx.core.djangoapps.content_libraries.auth.LtiAuthenticationBackend')
LMS_BASE = None
@@ -416,8 +341,6 @@ CMS_ROOT_URL = None
MAINTENANCE_BANNER_TEXT = 'Sample banner message'
WIKI_ENABLED = True
CERT_QUEUE = 'certificates'
################################# Middleware ###################################
@@ -510,27 +433,14 @@ EXTRA_MIDDLEWARE_CLASSES = []
############# XBlock Configuration ##########
# Import after sys.path fixup
from xmodule.modulestore.inheritance import InheritanceMixin
from xmodule.x_module import XModuleMixin, ResourceTemplates
# These are the Mixins that will be added to every Blocklike upon instantiation.
# DO NOT EXPAND THIS LIST!! We want it eventually to be EMPTY. Why? Because dynamically adding functions/behaviors to
# objects at runtime is confusing for both developers and static tooling (pylint/mypy). Instead...
# - to add special Blocklike behaviors just for your site: override `XBLOCK_EXTRA_MIXINS` with your own XBlockMixins.
# - to add new functionality to all Blocklikes: add it to the base Blocklike class in the core openedx/XBlock repo.
XBLOCK_MIXINS = (
# TODO: For each of these, either
# (a) merge their functionality into the base Blocklike class, or
# (b) refactor their functionality out of the Blocklike objects and into the edx-platform block runtimes.
LmsBlockMixin,
InheritanceMixin,
ResourceTemplates,
XModuleMixin,
EditInfoMixin,
# DO NOT EXPAND THIS LIST!! See declaration in openedx/envs/common.py for more information
mixins = list(XBLOCK_MIXINS)
mixins.insert(2, ResourceTemplates)
mixins += [
UpstreamSyncMixin, # Should be above AuthoringMixin for UpstreamSyncMixin.editor_saved to take effect
AuthoringMixin,
)
]
XBLOCK_MIXINS = tuple(mixins)
############################ ORA 2 ############################################
@@ -539,116 +449,19 @@ ORA2_FILE_PREFIX = 'default_env-default_deployment/ora2'
############################ Modulestore Configuration ################################
DOC_STORE_CONFIG = {
'db': 'edxapp',
'host': 'localhost',
'replicaSet': '',
'user': 'edxapp',
'port': 27017,
'collection': 'modulestore',
'ssl': False,
# https://api.mongodb.com/python/2.9.1/api/pymongo/mongo_client.html#module-pymongo.mongo_client
# default is never timeout while the connection is open,
#this means it needs to explicitly close raising pymongo.errors.NetworkTimeout
'socketTimeoutMS': 6000,
'connectTimeoutMS': 2000, # default is 20000, I believe raises pymongo.errors.ConnectionFailure
# Not setting waitQueueTimeoutMS and waitQueueMultiple since pymongo defaults to nobody being allowed to wait
'auth_source': None,
'read_preference': 'PRIMARY'
# If 'asset_collection' defined, it'll be used
# as the collection name for asset metadata.
# Otherwise, a default collection name will be used.
}
CONTENTSTORE = {
'ENGINE': 'xmodule.contentstore.mongo.MongoContentStore',
# connection strings are duplicated temporarily for
# backward compatibility
'OPTIONS': {
'db': 'edxapp',
'host': 'localhost',
'password': 'password',
'port': 27017,
'user': 'edxapp',
'ssl': False,
'auth_source': None
},
'ADDITIONAL_OPTIONS': {},
'DOC_STORE_CONFIG': DOC_STORE_CONFIG
}
CONTENTSTORE['DOC_STORE_CONFIG']['read_preference'] = 'PRIMARY'
MODULESTORE_BRANCH = 'draft-preferred'
MODULESTORE = {
'default': {
'ENGINE': 'xmodule.modulestore.mixed.MixedModuleStore',
'OPTIONS': {
'mappings': {},
'stores': [
{
'NAME': 'split',
'ENGINE': 'xmodule.modulestore.split_mongo.split_draft.DraftVersioningModuleStore',
'DOC_STORE_CONFIG': DOC_STORE_CONFIG,
'OPTIONS': {
'default_class': 'xmodule.hidden_block.HiddenBlock',
'fs_root': DATA_DIR,
'render_template': 'common.djangoapps.edxmako.shortcuts.render_to_string',
}
},
{
'NAME': 'draft',
'ENGINE': 'xmodule.modulestore.mongo.DraftMongoModuleStore',
'DOC_STORE_CONFIG': DOC_STORE_CONFIG,
'OPTIONS': {
'default_class': 'xmodule.hidden_block.HiddenBlock',
'fs_root': DATA_DIR,
'render_template': 'common.djangoapps.edxmako.shortcuts.render_to_string',
}
}
]
}
}
}
# Modulestore-level field override providers. These field override providers don't
# require student context.
MODULESTORE_FIELD_OVERRIDE_PROVIDERS = ()
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
DEFAULT_HASHING_ALGORITHM = 'sha256'
#################### Python sandbox ############################################
CODE_JAIL = {
# from https://github.com/openedx/codejail/blob/master/codejail/django_integration.py#L24, '' should be same as None
'python_bin': '/edx/app/edxapp/venvs/edxapp-sandbox/bin/python',
# User to run as in the sandbox.
'user': 'sandbox',
# Configurable limits.
'limits': {
# How many CPU seconds can jailed code use?
'CPU': 1,
# Limit the memory of the jailed process to something high but not
# infinite (512MiB in bytes)
'VMEM': 536870912,
# Time in seconds that the jailed process has to run.
'REALTIME': 3,
'PROXY': 0,
# Needs to be non-zero so that jailed code can use it as their temp directory.(1MiB in bytes)
'FSIZE': 1048576,
},
# Overrides to default configurable 'limits' (above).
# Keys should be course run ids.
# Values should be dictionaries that look like 'limits'.
"limit_overrides": {},
}
# Needs to be non-zero so that jailed code can use it as their temp directory.(1MiB in bytes)
CODE_JAIL['limits']['FSIZE'] = 1048576
############################ DJANGO_BUILTINS ################################
ROOT_URLCONF = 'cms.urls'
COURSE_IMPORT_EXPORT_BUCKET = ''
COURSE_METADATA_EXPORT_BUCKET = ''
@@ -684,48 +497,19 @@ PRESS_EMAIL = 'press@example.com'
STATIC_URL = '/static/studio/'
STATIC_ROOT = os.environ.get('STATIC_ROOT_CMS', ENV_ROOT / 'staticfiles' / 'studio')
STATICFILES_DIRS = [
COMMON_ROOT / "static",
PROJECT_ROOT / "static",
# Temporarily adding the following static path as we are migrating the built-in blocks' Sass to vanilla CSS.
# Once all of the built-in blocks are extracted from edx-platform, we can remove this static path.
# Relevant ticket: https://github.com/openedx/edx-platform/issues/35300
XMODULE_ROOT / "static",
]
# Storage
COURSE_IMPORT_EXPORT_STORAGE = 'django.core.files.storage.FileSystemStorage'
COURSE_METADATA_EXPORT_STORAGE = 'django.core.files.storage.FileSystemStorage'
STATICI18N_ROOT = PROJECT_ROOT / "static"
##### custom vendor plugin variables #####
############################### PIPELINE #######################################
PIPELINE = {
'PIPELINE_ENABLED': True,
# Don't use compression by default
'CSS_COMPRESSOR': None,
PIPELINE.update({
'JS_COMPRESSOR': None,
# Don't wrap JavaScript as there is code that depends upon updating the global namespace
'DISABLE_WRAPPER': True,
# Specify the UglifyJS binary to use
'UGLIFYJS_BINARY': 'node_modules/.bin/uglifyjs',
'COMPILERS': (),
'YUI_BINARY': 'yui-compressor',
}
STATICFILES_STORAGE_KWARGS = {}
# List of finder classes that know how to find static files in various locations.
# Note: the pipeline finder is included to be able to discover optimized files
STATICFILES_FINDERS = [
'openedx.core.djangoapps.theming.finders.ThemeFilesFinder',
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'openedx.core.lib.xblock_pipeline.finder.XBlockPipelineFinder',
'pipeline.finders.PipelineFinder',
]
})
PIPELINE['STYLESHEETS'] = {
'style-vendor': {
@@ -825,78 +609,23 @@ PIPELINE['JAVASCRIPT'] = {
},
}
STATICFILES_IGNORE_PATTERNS = (
"*.py",
"*.pyc",
# It would be nice if we could do, for example, "**/*.scss",
# but these strings get passed down to the `fnmatch` module,
# which doesn't support that. :(
# http://docs.python.org/2/library/fnmatch.html
"sass/*.scss",
"sass/*/*.scss",
"sass/*/*/*.scss",
"sass/*/*/*/*.scss",
# Ignore tests
"spec",
"spec_helpers",
# Symlinks used by js-test-tool
"xmodule_js",
"common_static",
)
STATICFILES_IGNORE_PATTERNS.append("common_static")
################################# DJANGO-REQUIRE ###############################
# The name of a build profile to use for your project, relative to REQUIRE_BASE_URL.
# A sensible value would be 'app.build.js'. Leave blank to use the built-in default build profile.
# Set to False to disable running the default profile (e.g. if only using it to build Standalone
# Modules)
REQUIRE_BUILD_PROFILE = "cms/js/build.js"
# The name of the require.js script used by your project, relative to REQUIRE_BASE_URL.
REQUIRE_JS = "js/vendor/requiresjs/require.js"
########################## DJANGO WEBPACK LOADER ##############################
WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': 'bundles/',
'STATS_FILE': os.path.join(STATIC_ROOT, 'webpack-stats.json'),
},
'WORKERS': {
'BUNDLE_DIR_NAME': 'bundles/',
'STATS_FILE': os.path.join(STATIC_ROOT, 'webpack-worker-stats.json')
}
}
############################ SERVICE_VARIANT ##################################
# SERVICE_VARIANT specifies name of the variant used, which decides what JSON
# configuration files are read during startup.
SERVICE_VARIANT = os.environ.get('SERVICE_VARIANT', 'cms')
# CONFIG_PREFIX specifies the prefix of the JSON configuration files,
# based on the service variant. If no variant is use, don't use a
# prefix.
CONFIG_PREFIX = SERVICE_VARIANT + "." if SERVICE_VARIANT else ""
SERVICE_VARIANT = 'cms'
################################# CELERY ######################################
# Name the exchange and queues for each variant
QUEUE_VARIANT = CONFIG_PREFIX.lower()
CELERY_DEFAULT_EXCHANGE = f'edx.{QUEUE_VARIANT}core'
HIGH_PRIORITY_QUEUE = f'edx.{QUEUE_VARIANT}core.high'
DEFAULT_PRIORITY_QUEUE = f'edx.{QUEUE_VARIANT}core.default'
LOW_PRIORITY_QUEUE = f'edx.{QUEUE_VARIANT}core.low'
CELERY_DEFAULT_QUEUE = DEFAULT_PRIORITY_QUEUE
CELERY_DEFAULT_ROUTING_KEY = DEFAULT_PRIORITY_QUEUE
# Name the exchange and queues w.r.t the SERVICE_VARIANT
HIGH_PRIORITY_QUEUE = f'edx.{SERVICE_VARIANT}.core.high'
DEFAULT_PRIORITY_QUEUE = f'edx.{SERVICE_VARIANT}.core.default'
LOW_PRIORITY_QUEUE = f'edx.{SERVICE_VARIANT}.core.low'
CELERY_QUEUES = {
HIGH_PRIORITY_QUEUE: {},
@@ -904,17 +633,11 @@ CELERY_QUEUES = {
LOW_PRIORITY_QUEUE: {},
}
# Queues configuration
CLEAR_REQUEST_CACHE_ON_TASK_COMPLETION = True
BROKER_USE_SSL = Derived(lambda settings: settings.CELERY_BROKER_USE_SSL)
CELERY_ALWAYS_EAGER = False
############################## HEARTBEAT ######################################
HEARTBEAT_CELERY_ROUTING_KEY = HIGH_PRIORITY_QUEUE
BROKER_USE_SSL = Derived(lambda settings: settings.CELERY_BROKER_USE_SSL)
############################## Video ##########################################
@@ -923,12 +646,7 @@ EXTENDED_VIDEO_TRANSCRIPT_LANGUAGES = []
############################# SETTINGS FOR VIDEO UPLOAD PIPELINE #############################
VIDEO_UPLOAD_PIPELINE = {
'VEM_S3_BUCKET': '',
'BUCKET': '',
'ROOT_PATH': '',
'CONCURRENT_UPLOAD_LIMIT': 4,
}
VIDEO_UPLOAD_PIPELINE['CONCURRENT_UPLOAD_LIMIT'] = 4
############################ APPS #####################################
@@ -1193,131 +911,14 @@ INSTALLED_APPS = [
"openedx_learning.apps.authoring.sections",
]
################# EDX MARKETING SITE ##################################
MKTG_URL_LINK_MAP = {}
ID_VERIFICATION_SUPPORT_LINK = ''
PASSWORD_RESET_SUPPORT_LINK = ''
ACTIVATION_EMAIL_SUPPORT_LINK = ''
LOGIN_ISSUE_SUPPORT_LINK = ''
############################## EVENT TRACKING #################################
TRACK_MAX_EVENT = 50000
TRACKING_BACKENDS = {
'logger': {
'ENGINE': 'common.djangoapps.track.backends.logger.LoggerBackend',
'OPTIONS': {
'name': 'tracking'
}
}
}
# We're already logging events, and we don't want to capture user
# names/passwords. Heartbeat events are likely not interesting.
TRACKING_IGNORE_URL_PATTERNS = [r'^/event', r'^/login', r'^/heartbeat']
EVENT_TRACKING_ENABLED = True
EVENT_TRACKING_BACKENDS = {
'tracking_logs': {
'ENGINE': 'eventtracking.backends.routing.RoutingBackend',
'OPTIONS': {
'backends': {
'logger': {
'ENGINE': 'eventtracking.backends.logger.LoggerBackend',
'OPTIONS': {
'name': 'tracking',
'max_event_size': TRACK_MAX_EVENT,
}
}
},
'processors': [
{'ENGINE': 'common.djangoapps.track.shim.LegacyFieldMappingProcessor'},
{'ENGINE': 'common.djangoapps.track.shim.PrefixedEventProcessor'}
]
}
},
'segmentio': {
'ENGINE': 'eventtracking.backends.routing.RoutingBackend',
'OPTIONS': {
'backends': {
'segment': {'ENGINE': 'eventtracking.backends.segment.SegmentBackend'}
},
'processors': [
{
'ENGINE': 'eventtracking.processors.whitelist.NameWhitelistProcessor',
'OPTIONS': {
'whitelist': []
}
},
{
'ENGINE': 'common.djangoapps.track.shim.GoogleAnalyticsProcessor'
}
]
}
}
}
EVENT_TRACKING_PROCESSORS = []
EVENT_TRACKING_SEGMENTIO_EMIT_WHITELIST = []
### Apps only installed in some instances
add_optional_apps(OPTIONAL_APPS, INSTALLED_APPS)
##### ACCOUNT LOCKOUT DEFAULT PARAMETERS #####
MAX_FAILED_LOGIN_ATTEMPTS_ALLOWED = 6
MAX_FAILED_LOGIN_ATTEMPTS_LOCKOUT_PERIOD_SECS = 30 * 60
### Apps only installed in some instances
# The order of INSTALLED_APPS matters, so this tuple is the app name and the item in INSTALLED_APPS
# that this app should be inserted *before*. A None here means it should be appended to the list.
OPTIONAL_APPS = (
('problem_builder', 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig'),
('edx_sga', None),
# edx-ora2
('submissions', 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig'),
('openassessment', 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig'),
('openassessment.assessment', 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig'),
('openassessment.fileupload', 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig'),
('openassessment.staffgrader', 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig'),
('openassessment.workflow', 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig'),
('openassessment.xblock', 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig'),
# edxval
('edxval', 'openedx.core.djangoapps.content.course_overviews.apps.CourseOverviewsConfig'),
# Enterprise App (http://github.com/openedx/edx-enterprise)
('enterprise', None),
('consent', None),
('integrated_channels.integrated_channel', None),
('integrated_channels.degreed', None),
('integrated_channels.degreed2', None),
('integrated_channels.sap_success_factors', None),
('integrated_channels.xapi', None),
('integrated_channels.cornerstone', None),
('integrated_channels.blackboard', None),
('integrated_channels.canvas', None),
('integrated_channels.moodle', None),
)
for app_name, insert_before in OPTIONAL_APPS:
# First attempt to only find the module rather than actually importing it,
# to avoid circular references - only try to import if it can't be found
# by find_spec, which doesn't work with import hooks
if importlib.util.find_spec(app_name) is None:
try:
__import__(app_name)
except ImportError:
continue
try:
INSTALLED_APPS.insert(INSTALLED_APPS.index(insert_before), app_name)
except (IndexError, ValueError):
INSTALLED_APPS.append(app_name)
### Size of chunks into which asset uploads will be divided
UPLOAD_CHUNK_SIZE_IN_MB = 10
@@ -1413,27 +1014,11 @@ ELASTIC_FIELD_MAPPINGS = {
XBLOCK_FS_STORAGE_BUCKET = None
XBLOCK_FS_STORAGE_PREFIX = None
############################ Global Database Configuration #####################
DATABASE_ROUTERS = [
'openedx.core.lib.django_courseware_routers.StudentModuleHistoryExtendedRouter',
]
############################ OAUTH2 Provider ###################################
# 5 minute expiration time for JWT id tokens issued for external API requests.
OAUTH_ID_TOKEN_EXPIRATION = 5 * 60
EDX_DRF_EXTENSIONS = {
# Set this value to an empty dict in order to prevent automatically updating
# user data from values in (possibly stale) JWTs.
'JWT_PAYLOAD_USER_ATTRIBUTE_MAPPING': {},
}
############## Settings for Studio Context Sensitive Help ##############
HELP_TOKENS_INI_FILE = REPO_ROOT / "cms" / "envs" / "help_tokens.ini"
############## DJANGO-USER-TASKS ##############
# How long until database records about the outcome of a task and its artifacts get deleted?
@@ -1441,9 +1026,6 @@ USER_TASKS_MAX_AGE = timedelta(days=7)
############################# Persistent Grades ####################################
# Queue to use for updating persistent grades
RECALCULATE_GRADES_ROUTING_KEY = DEFAULT_PRIORITY_QUEUE
# .. setting_name: DEFAULT_GRADE_DESIGNATIONS
# .. setting_default: ['A', 'B', 'C', 'D']
# .. setting_description: The default 'pass' grade cutoff designations to be used. The failure grade
@@ -1534,10 +1116,6 @@ VIDEO_IMAGE_SETTINGS = dict(
VIDEO_IMAGE_MAX_AGE = 31536000
########################## VIDEO TRANSCRIPTS STORAGE ############################
TRANSCRIPT_LANG_CACHE_TIMEOUT = 60 * 60 * 24
##### shoppingcart Payment #####
PAYMENT_SUPPORT_EMAIL = 'billing@example.com'
@@ -1582,19 +1160,7 @@ LEARNER_PORTAL_URL_ROOT = 'https://learner-portal-localhost:18000'
############################ JWT #################################
REGISTRATION_EXTRA_FIELDS = {
'confirm_email': 'hidden',
'level_of_education': 'optional',
'gender': 'optional',
'year_of_birth': 'optional',
'mailing_address': 'optional',
'goals': 'optional',
'honor_code': 'required',
'terms_of_service': 'hidden',
'city': 'hidden',
'country': 'hidden',
'marketing_emails_opt_in': 'hidden',
}
REGISTRATION_EXTRA_FIELDS['marketing_emails_opt_in'] = 'hidden'
EDXAPP_PARSE_KEYS = {}
PARSE_KEYS = {}
@@ -1675,18 +1241,7 @@ DISCUSSIONS_INCONTEXT_LEARNMORE_URL = "https://docs.openedx.org/en/latest/educat
def _should_send_xblock_events(settings):
return settings.ENABLE_SEND_XBLOCK_LIFECYCLE_EVENTS_OVER_BUS
# .. setting_name: EVENT_BUS_PRODUCER_CONFIG
# .. setting_default: all events disabled
# .. setting_description: Dictionary of event_types mapped to dictionaries of topic to topic-related configuration.
# Each topic configuration dictionary contains
# * `enabled`: a toggle denoting whether the event will be published to the topic. These should be annotated
# according to
# https://docs.openedx.org/projects/edx-toggles/en/latest/how_to/documenting_new_feature_toggles.html
# * `event_key_field` which is a period-delimited string path to event data field to use as event key.
# Note: The topic names should not include environment prefix as it will be dynamically added based on
# EVENT_BUS_TOPIC_PREFIX setting.
EVENT_BUS_PRODUCER_CONFIG = {
EVENT_BUS_PRODUCER_CONFIG.update({
'org.openedx.content_authoring.course.catalog_info.changed.v1': {
'course-catalog-info-changed':
{'event_key_field': 'catalog_info.course_key',
@@ -1714,29 +1269,7 @@ EVENT_BUS_PRODUCER_CONFIG = {
'course-authoring-xblock-lifecycle':
{'event_key_field': 'xblock_info.usage_key', 'enabled': Derived(_should_send_xblock_events)},
},
# LMS events. These have to be copied over here because lms.common adds some derived entries as well,
# and the derivation fails if the keys are missing. If we ever remove the import of lms.common, we can remove these.
'org.openedx.learning.certificate.created.v1': {
'learning-certificate-lifecycle':
{'event_key_field': 'certificate.course.course_key', 'enabled': False},
},
'org.openedx.learning.certificate.revoked.v1': {
'learning-certificate-lifecycle':
{'event_key_field': 'certificate.course.course_key', 'enabled': False},
},
"org.openedx.learning.course.passing.status.updated.v1": {
"learning-badges-lifecycle": {
"event_key_field": "course_passing_status.course.course_key",
"enabled": Derived(should_send_learning_badge_events),
},
},
"org.openedx.learning.ccx.course.passing.status.updated.v1": {
"learning-badges-lifecycle": {
"event_key_field": "course_passing_status.course.ccx_course_key",
"enabled": Derived(should_send_learning_badge_events),
},
},
}
})
################### Authoring API ######################

View File

@@ -134,8 +134,6 @@ if STATIC_URL_BASE:
if STATIC_ROOT_BASE:
STATIC_ROOT = path(STATIC_ROOT_BASE) / 'studio'
WEBPACK_LOADER['DEFAULT']['STATS_FILE'] = STATIC_ROOT / "webpack-stats.json"
WEBPACK_LOADER['WORKERS']['STATS_FILE'] = STATIC_ROOT / "webpack-worker-stats.json"
DATA_DIR = path(DATA_DIR)
@@ -263,7 +261,7 @@ if _YAML_CELERY_QUEUES:
# Then add alternate environment queues
_YAML_ALTERNATE_WORKER_QUEUES = _YAML_TOKENS.get('ALTERNATE_WORKER_QUEUES', '').split()
ALTERNATE_QUEUES = [
DEFAULT_PRIORITY_QUEUE.replace(QUEUE_VARIANT, alternate + '.')
DEFAULT_PRIORITY_QUEUE.replace(SERVICE_VARIANT, alternate)
for alternate in _YAML_ALTERNATE_WORKER_QUEUES
]

View File

@@ -14,6 +14,7 @@ sessions. Assumes structure:
import os
import tempfile
from django.utils.translation import gettext_lazy
from edx_django_utils.plugins import add_plugins
@@ -38,7 +39,8 @@ STUDIO_SHORT_NAME = gettext_lazy("𝓢𝓽𝓾𝓭𝓲𝓸")
COMMON_TEST_DATA_ROOT = COMMON_ROOT / "test" / "data"
WEBPACK_LOADER["DEFAULT"]["STATS_FILE"] = STATIC_ROOT / "webpack-stats.json"
COMPREHENSIVE_THEME_DIRS = [REPO_ROOT / "themes", REPO_ROOT / "common/test"]
WEBPACK_LOADER['DEFAULT']['LOADER_CLASS'] = 'webpack_loader.loader.FakeWebpackLoader'
GITHUB_REPO_ROOT = TEST_ROOT / "data"