tutor 22.0.2__tar.gz → 22.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tutor-22.0.2 → tutor-22.0.3}/PKG-INFO +4 -4
- {tutor-22.0.2 → tutor-22.0.3}/requirements/base.in +1 -2
- {tutor-22.0.2 → tutor-22.0.3}/requirements/dev.txt +2 -2
- {tutor-22.0.2 → tutor-22.0.3}/tutor/__about__.py +1 -1
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/config.py +5 -5
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/images.py +1 -1
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/mounts.py +1 -1
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/params.py +5 -1
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/plugins.py +2 -2
- {tutor-22.0.2 → tutor-22.0.3}/tutor/config.py +25 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/hooks/catalog.py +5 -1
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/lms/development.py +1 -3
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/partials/common_all.py +11 -3
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/partials/common_cms.py +1 -1
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/partials/common_lms.py +4 -4
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/Dockerfile +14 -4
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/config/defaults.yml +1 -1
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/jobs/init/mysql.sh +7 -1
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/local/docker-compose.jobs.yml +4 -0
- {tutor-22.0.2 → tutor-22.0.3}/.gitignore +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/.hatch_build.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/LICENSE.txt +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/README.rst +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/pyproject.toml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/requirements/plugins.txt +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/bindmount.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/cli.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/compose.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/context.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/dev.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/jobs.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/jobs_utils.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/k8s.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/local.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/upgrade/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/upgrade/common.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/upgrade/compose.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/commands/upgrade/k8s.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/core/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/core/hooks/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/core/hooks/actions.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/core/hooks/contexts.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/core/hooks/filters.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/core/hooks/priorities.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/env.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/exceptions.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/fmt.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/hooks/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/images.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/interactive.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/plugins/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/plugins/base.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/plugins/indexes.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/plugins/openedx.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/plugins/v0.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/plugins/v1.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/py.typed +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/serialize.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/tasks.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/caddy/Caddyfile +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/config/cms.env.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/config/lms.env.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/config/partials/auth.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/cms/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/cms/development.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/cms/production.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/cms/test.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/lms/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/lms/production.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/lms/test.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/settings/partials/common_test.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/openedx/uwsgi.ini +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/permissions/setowners.sh +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/apps/redis/redis.conf +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/bin/reload-uwsgi +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/revisions.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/settings/cms/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/settings/cms/assets.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/settings/cms/i18n.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/settings/lms/__init__.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/settings/lms/assets.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/settings/lms/i18n.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/settings/partials/assets.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/settings/partials/i18n.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/settings/uwsgi.ini +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/openedx/themes/README +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/permissions/Dockerfile +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/build/permissions/setowner.sh +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/config/base.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/dev/docker-compose.jobs.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/dev/docker-compose.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/jobs/init/cms.sh +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/jobs/init/lms.sh +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/jobs/init/meilisearch.sh +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/jobs/init/mounted-directories.sh +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/k8s/deployments.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/k8s/jobs.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/k8s/namespace.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/k8s/override.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/k8s/services.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/k8s/volumes.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/kustomization.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/local/docker-compose.prod.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/local/docker-compose.yml +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/templates/version +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/types.py +0 -0
- {tutor-22.0.2 → tutor-22.0.3}/tutor/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: tutor
|
|
3
|
-
Version: 22.0.
|
|
3
|
+
Version: 22.0.3
|
|
4
4
|
Summary: The Docker-based Open edX distribution designed for peace of mind
|
|
5
5
|
Project-URL: Homepage, https://docs.tutor.edly.io/
|
|
6
6
|
Project-URL: Documentation, https://docs.tutor.edly.io/
|
|
@@ -24,7 +24,7 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
24
24
|
Classifier: Programming Language :: Python :: 3.14
|
|
25
25
|
Requires-Python: >=3.10
|
|
26
26
|
Requires-Dist: appdirs
|
|
27
|
-
Requires-Dist: click
|
|
27
|
+
Requires-Dist: click>=8.4
|
|
28
28
|
Requires-Dist: importlib-metadata>=7.0.1
|
|
29
29
|
Requires-Dist: importlib-resources>=6.1.1
|
|
30
30
|
Requires-Dist: jinja2>=2.10
|
|
@@ -41,10 +41,10 @@ Requires-Dist: attrs==26.1.0; extra == 'dev'
|
|
|
41
41
|
Requires-Dist: backports-tarfile==1.2.0; extra == 'dev'
|
|
42
42
|
Requires-Dist: build==1.4.4; extra == 'dev'
|
|
43
43
|
Requires-Dist: cachetools==5.5.2; extra == 'dev'
|
|
44
|
-
Requires-Dist: certifi==
|
|
44
|
+
Requires-Dist: certifi==2026.10.19; extra == 'dev'
|
|
45
45
|
Requires-Dist: charset-normalizer==3.4.7; extra == 'dev'
|
|
46
46
|
Requires-Dist: click-log==0.4.0; extra == 'dev'
|
|
47
|
-
Requires-Dist: click==8.
|
|
47
|
+
Requires-Dist: click==8.5.0; extra == 'dev'
|
|
48
48
|
Requires-Dist: coverage==7.10.7; extra == 'dev'
|
|
49
49
|
Requires-Dist: docutils==0.22.4; extra == 'dev'
|
|
50
50
|
Requires-Dist: durationpy==0.10; extra == 'dev'
|
|
@@ -20,7 +20,7 @@ cachetools==5.5.2
|
|
|
20
20
|
# via
|
|
21
21
|
# -r requirements/base.txt
|
|
22
22
|
# google-auth
|
|
23
|
-
certifi==
|
|
23
|
+
certifi==2026.10.19
|
|
24
24
|
# via
|
|
25
25
|
# -r requirements/base.txt
|
|
26
26
|
# kubernetes
|
|
@@ -29,7 +29,7 @@ charset-normalizer==3.4.7
|
|
|
29
29
|
# via
|
|
30
30
|
# -r requirements/base.txt
|
|
31
31
|
# requests
|
|
32
|
-
click==8.
|
|
32
|
+
click==8.5.0
|
|
33
33
|
# via
|
|
34
34
|
# -r requirements/base.txt
|
|
35
35
|
# click-log
|
|
@@ -2,7 +2,7 @@ import os
|
|
|
2
2
|
|
|
3
3
|
# Increment this version number to trigger a new release. See
|
|
4
4
|
# docs/tutor.html#versioning for information on the versioning scheme.
|
|
5
|
-
__version__ = "22.0.
|
|
5
|
+
__version__ = "22.0.3"
|
|
6
6
|
|
|
7
7
|
# The version suffix will be appended to the actual version, separated by a
|
|
8
8
|
# dash. Use this suffix to differentiate between the actual released version and
|
|
@@ -12,7 +12,7 @@ from tutor import config as tutor_config
|
|
|
12
12
|
from tutor import env, exceptions, fmt, hooks, serialize, utils
|
|
13
13
|
from tutor import interactive as interactive_config
|
|
14
14
|
from tutor.commands.context import Context
|
|
15
|
-
from tutor.commands.params import ConfigLoaderParam
|
|
15
|
+
from tutor.commands.params import ConfigLoaderParam, ParamValue
|
|
16
16
|
from tutor.types import Config, ConfigValue
|
|
17
17
|
|
|
18
18
|
|
|
@@ -25,7 +25,7 @@ def config_command() -> None:
|
|
|
25
25
|
pass
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class ConfigKeyParamType(ConfigLoaderParam):
|
|
28
|
+
class ConfigKeyParamType(ConfigLoaderParam[ParamValue]):
|
|
29
29
|
name = "configkey"
|
|
30
30
|
|
|
31
31
|
def shell_complete(
|
|
@@ -49,7 +49,7 @@ class ConfigKeyParamType(ConfigLoaderParam):
|
|
|
49
49
|
yield from self.config.items()
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
class ConfigKeyValParamType(ConfigKeyParamType):
|
|
52
|
+
class ConfigKeyValParamType(ConfigKeyParamType[tuple[str, t.Any]]):
|
|
53
53
|
"""
|
|
54
54
|
Parser for <KEY>=<YAML VALUE> command line arguments.
|
|
55
55
|
"""
|
|
@@ -131,7 +131,7 @@ class ConfigListKeyValParamType(ConfigKeyValParamType):
|
|
|
131
131
|
"--unset",
|
|
132
132
|
"unset_vars",
|
|
133
133
|
multiple=True,
|
|
134
|
-
type=ConfigKeyParamType(),
|
|
134
|
+
type=ConfigKeyParamType[str](),
|
|
135
135
|
help="Remove a configuration value (can be used multiple times)",
|
|
136
136
|
)
|
|
137
137
|
@click.option(
|
|
@@ -221,7 +221,7 @@ def printroot(context: Context) -> None:
|
|
|
221
221
|
|
|
222
222
|
|
|
223
223
|
@click.command(help="Print a configuration value")
|
|
224
|
-
@click.argument("key", type=ConfigKeyParamType())
|
|
224
|
+
@click.argument("key", type=ConfigKeyParamType[str]())
|
|
225
225
|
@click.pass_obj
|
|
226
226
|
def printvalue(context: Context, key: str) -> None:
|
|
227
227
|
config = tutor_config.load(context.root)
|
|
@@ -6,8 +6,12 @@ from tutor import config as tutor_config
|
|
|
6
6
|
from tutor import hooks
|
|
7
7
|
from tutor.types import Config
|
|
8
8
|
|
|
9
|
+
# Type of the value produced by the param type `convert` method. Since click 8.4,
|
|
10
|
+
# `click.ParamType` is generic and must be parameterized with that type.
|
|
11
|
+
ParamValue = t.TypeVar("ParamValue")
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
|
|
14
|
+
class ConfigLoaderParam(click.ParamType[ParamValue]):
|
|
11
15
|
"""
|
|
12
16
|
Convenient param child class that automatically loads the user configuration on auto-complete.
|
|
13
17
|
"""
|
|
@@ -19,7 +19,7 @@ from tutor.types import Config
|
|
|
19
19
|
from .context import Context
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class PluginName(click.ParamType):
|
|
22
|
+
class PluginName(click.ParamType[str]):
|
|
23
23
|
"""
|
|
24
24
|
Convenient param type that supports autocompletion of installed plugin names.
|
|
25
25
|
"""
|
|
@@ -44,7 +44,7 @@ class PluginName(click.ParamType):
|
|
|
44
44
|
return [name for name in candidates if name.startswith(incomplete)]
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
class IndexPluginName(click.ParamType):
|
|
47
|
+
class IndexPluginName(click.ParamType[str]):
|
|
48
48
|
"""
|
|
49
49
|
Param type for auto-completion of plugin names found in index cache.
|
|
50
50
|
"""
|
|
@@ -9,6 +9,11 @@ from tutor.types import Config, ConfigValue, cast_config, get_typed
|
|
|
9
9
|
|
|
10
10
|
CONFIG_FILENAME = "config.yml"
|
|
11
11
|
|
|
12
|
+
# Default value of the MEILISEARCH_URL setting. It is duplicated here from
|
|
13
|
+
# config/defaults.yml because loading the configuration defaults is slow. The
|
|
14
|
+
# two values are checked to be in sync by the unit tests.
|
|
15
|
+
MEILISEARCH_URL_DEFAULT = "http://meilisearch:7700"
|
|
16
|
+
|
|
12
17
|
|
|
13
18
|
def load(root: str) -> Config:
|
|
14
19
|
"""
|
|
@@ -342,3 +347,23 @@ def _update_enabled_plugins_on_unload(_plugin: str, _root: str, config: Config)
|
|
|
342
347
|
Note that this action must be performed after the plugin has been unloaded, hence the low priority.
|
|
343
348
|
"""
|
|
344
349
|
save_enabled_plugins(config)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
@hooks.Actions.CONFIG_LOADED.add()
|
|
353
|
+
def _check_meilisearch_url(config: Config) -> None:
|
|
354
|
+
"""
|
|
355
|
+
Warn the user in case Meilisearch is not run by Tutor while MEILISEARCH_URL
|
|
356
|
+
still points at the Tutor-managed instance.
|
|
357
|
+
|
|
358
|
+
Meilisearch is a required component of the Open edX platform: RUN_MEILISEARCH=false
|
|
359
|
+
does not disable it, it only indicates that it is hosted externally.
|
|
360
|
+
"""
|
|
361
|
+
if get_typed(config, "RUN_MEILISEARCH", bool, True):
|
|
362
|
+
return
|
|
363
|
+
if get_typed(config, "MEILISEARCH_URL", str, "") == MEILISEARCH_URL_DEFAULT:
|
|
364
|
+
fmt.echo_alert(
|
|
365
|
+
f'Warning: RUN_MEILISEARCH=false, but MEILISEARCH_URL is still set to its default value "{MEILISEARCH_URL_DEFAULT}". '
|
|
366
|
+
"Meilisearch is a required component of the Open edX platform, so RUN_MEILISEARCH=false only means that it is hosted "
|
|
367
|
+
"externally. Set MEILISEARCH_URL to the URL of an existing, preconfigured Meilisearch instance, or set "
|
|
368
|
+
"RUN_MEILISEARCH=true to have Tutor run its own."
|
|
369
|
+
)
|
|
@@ -287,6 +287,10 @@ class Filters:
|
|
|
287
287
|
DOCKER_BUILD_COMMAND: Filter[list[str], []] = Filter()
|
|
288
288
|
|
|
289
289
|
#: List of patches that should be inserted in a given location of the templates.
|
|
290
|
+
#: Each ``{{ patch("name") }}`` statement in the templates is replaced by the
|
|
291
|
+
#: rendered content of all the patches with the same name. See :ref:`template_patches`
|
|
292
|
+
#: for a detailed explanation and the :ref:`template patch catalog <patches>` for
|
|
293
|
+
#: the list of all available patches.
|
|
290
294
|
#:
|
|
291
295
|
#: :parameter list[tuple[str, str]] patches: pairs of (name, content) tuples. Use this
|
|
292
296
|
#: filter to modify the Tutor templates.
|
|
@@ -325,7 +329,7 @@ class Filters:
|
|
|
325
329
|
#: - ``list_if``: In a list of ``(value, condition)`` tuples, return the list of ``value`` for which the ``condition`` is true.
|
|
326
330
|
#: - ``long_to_base64``: Base-64 encode a long integer.
|
|
327
331
|
#: - ``iter_values_named``: Yield the values of the configuration settings that match a certain pattern. Example: ``{% for value in iter_values_named(prefix="KEY", suffix="SUFFIX")%}...{% endfor %}``. By default, only non-empty values are yielded. To iterate also on empty values, pass the ``allow_empty=True`` argument.
|
|
328
|
-
#: - ``patch``: See :ref:`
|
|
332
|
+
#: - ``patch``: See :ref:`template_patches`.
|
|
329
333
|
#: - ``random_string``: Return a random string of the given length composed of ASCII letters and digits. Example: ``{{ 8|random_string }}``.
|
|
330
334
|
#: - ``reverse_host``: Reverse a domain name (see `reference <https://en.wikipedia.org/wiki/Reverse_domain_name_notation>`__). Example: ``{{ "demo.myopenedx.com"|reverse_host }}`` is equal to "com.myopenedx.demo".
|
|
331
335
|
#: - ``rsa_import_key``: Import a PEM-formatted RSA key and return the corresponding object.
|
|
@@ -26,10 +26,8 @@ SESSION_COOKIE_SAMESITE = "Lax"
|
|
|
26
26
|
# CMS authentication
|
|
27
27
|
IDA_LOGOUT_URI_LIST.append("http://{{ CMS_HOST }}:8001/logout/")
|
|
28
28
|
|
|
29
|
-
FEATURES["ENABLE_COURSEWARE_MICROFRONTEND"] = False
|
|
30
|
-
|
|
31
29
|
# Disable enterprise integration
|
|
32
|
-
|
|
30
|
+
ENABLE_ENTERPRISE_INTEGRATION = False
|
|
33
31
|
SYSTEM_WIDE_ROLE_CLASSES.remove("enterprise.SystemWideEnterpriseUserRoleAssignment")
|
|
34
32
|
|
|
35
33
|
LOGGING["loggers"]["oauth2_provider"] = {
|
|
@@ -4,6 +4,14 @@ import os
|
|
|
4
4
|
|
|
5
5
|
from xmodule.modulestore.modulestore_settings import update_module_store_settings
|
|
6
6
|
|
|
7
|
+
# Re-bind the FEATURES proxy to this settings module, so that both flat feature
|
|
8
|
+
# settings and legacy FEATURES["..."] reads and writes resolve here.
|
|
9
|
+
try:
|
|
10
|
+
from openedx.core.lib.features_setting_proxy import FeaturesProxy
|
|
11
|
+
FEATURES = FeaturesProxy(globals())
|
|
12
|
+
except ImportError:
|
|
13
|
+
pass
|
|
14
|
+
|
|
7
15
|
# Mongodb connection parameters: simply modify `mongodb_parameters` to affect all connections to MongoDb.
|
|
8
16
|
mongodb_parameters = {
|
|
9
17
|
"db": "{{ MONGODB_DATABASE }}",
|
|
@@ -229,9 +237,9 @@ JWT_AUTH["JWT_ISSUERS"] = [
|
|
|
229
237
|
]
|
|
230
238
|
|
|
231
239
|
# Enable/Disable some features globally
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
240
|
+
ENABLE_DISCUSSION_SERVICE = False
|
|
241
|
+
PREVENT_CONCURRENT_LOGINS = False
|
|
242
|
+
ENABLE_CORS_HEADERS = True
|
|
235
243
|
|
|
236
244
|
# CORS
|
|
237
245
|
CORS_ALLOW_CREDENTIALS = True
|
|
@@ -21,7 +21,7 @@ FRONTEND_LOGIN_URL = LMS_ROOT_URL + '/login'
|
|
|
21
21
|
FRONTEND_REGISTER_URL = LMS_ROOT_URL + '/register'
|
|
22
22
|
|
|
23
23
|
# Enable "reindex" button
|
|
24
|
-
|
|
24
|
+
ENABLE_COURSEWARE_INDEX = True
|
|
25
25
|
|
|
26
26
|
# Create folders if necessary
|
|
27
27
|
for folder in [LOG_DIR, MEDIA_ROOT, STATIC_ROOT, ORA2_FILEUPLOAD_ROOT]:
|
|
@@ -21,7 +21,7 @@ OAUTH_ENFORCE_SECURE = False
|
|
|
21
21
|
# Email settings
|
|
22
22
|
DEFAULT_EMAIL_LOGO_URL = LMS_ROOT_URL + "/theming/asset/images/logo.png"
|
|
23
23
|
BULK_EMAIL_SEND_USING_EDX_ACE = True
|
|
24
|
-
|
|
24
|
+
ENABLE_FOOTER_MOBILE_APP_LINKS = False
|
|
25
25
|
|
|
26
26
|
# Branding
|
|
27
27
|
MOBILE_STORE_ACE_URLS = {}
|
|
@@ -38,9 +38,9 @@ CACHES["staticfiles"] = {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
# Enable search features
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
ENABLE_COURSE_DISCOVERY = True
|
|
42
|
+
ENABLE_COURSEWARE_SEARCH = True
|
|
43
|
+
ENABLE_DASHBOARD_SEARCH = True
|
|
44
44
|
|
|
45
45
|
# Create folders if necessary
|
|
46
46
|
for folder in [DATA_DIR, LOG_DIR, MEDIA_ROOT, STATIC_ROOT, ORA2_FILEUPLOAD_ROOT]:
|
|
@@ -8,10 +8,10 @@ ENV DEBIAN_FRONTEND=noninteractive
|
|
|
8
8
|
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
|
9
9
|
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
|
10
10
|
apt update && \
|
|
11
|
-
apt install -y build-essential curl git language-pack-en
|
|
11
|
+
apt install -y build-essential ca-certificates curl git language-pack-en
|
|
12
12
|
ENV LC_ALL=en_US.UTF-8
|
|
13
13
|
|
|
14
|
-
COPY --from=ghcr.io/astral-sh/uv:0.
|
|
14
|
+
COPY --from=ghcr.io/astral-sh/uv:0.13.5 /uv /usr/local/bin/uv
|
|
15
15
|
ARG PIP_COMMAND="uv pip"
|
|
16
16
|
|
|
17
17
|
# Constrain the build-time setuptools used in the isolated (PEP 517) build
|
|
@@ -23,6 +23,8 @@ ARG PIP_COMMAND="uv pip"
|
|
|
23
23
|
RUN echo "setuptools==80.9.0" > /etc/openedx-build-constraints.txt
|
|
24
24
|
ENV UV_BUILD_CONSTRAINT=/etc/openedx-build-constraints.txt
|
|
25
25
|
ENV PIP_CONSTRAINT=/etc/openedx-build-constraints.txt
|
|
26
|
+
# pip 26 no longer applies PIP_CONSTRAINT to build dependencies
|
|
27
|
+
ENV PIP_BUILD_CONSTRAINT=/etc/openedx-build-constraints.txt
|
|
26
28
|
|
|
27
29
|
{{ patch("openedx-dockerfile-minimal") }}
|
|
28
30
|
|
|
@@ -110,7 +112,7 @@ RUN --mount=type=cache,target=/openedx/.cache/pip,sharing=shared \
|
|
|
110
112
|
# https://pypi.org/project/setuptools/
|
|
111
113
|
# https://pypi.org/project/pip/
|
|
112
114
|
# https://pypi.org/project/wheel/
|
|
113
|
-
setuptools pip==
|
|
115
|
+
setuptools pip==26.2.2 wheel==0.43.0
|
|
114
116
|
|
|
115
117
|
# Install base requirements and asset-building requirements
|
|
116
118
|
RUN --mount=type=bind,from=edx-platform,source=/requirements/edx/base.txt,target=/openedx/edx-platform/requirements/edx/base.txt \
|
|
@@ -118,6 +120,11 @@ RUN --mount=type=bind,from=edx-platform,source=/requirements/edx/base.txt,target
|
|
|
118
120
|
--mount=type=cache,target=/openedx/.cache/pip,sharing=shared \
|
|
119
121
|
$PIP_COMMAND install -r /openedx/edx-platform/requirements/edx/base.txt -r /openedx/edx-platform/requirements/edx/assets.txt
|
|
120
122
|
|
|
123
|
+
# Upgrade certifi until edx-platform pins a version without the compromised emSign roots
|
|
124
|
+
# https://emudhra.we-have-a-problem.com/
|
|
125
|
+
RUN --mount=type=cache,target=/openedx/.cache/pip,sharing=shared \
|
|
126
|
+
$PIP_COMMAND install "certifi>=2026.10.19"
|
|
127
|
+
|
|
121
128
|
# Install extra requirements
|
|
122
129
|
RUN --mount=type=cache,target=/openedx/.cache/pip,sharing=shared \
|
|
123
130
|
$PIP_COMMAND install \
|
|
@@ -150,7 +157,7 @@ ENV PATH=/openedx/nodeenv/bin:/openedx/venv/bin:${PATH}
|
|
|
150
157
|
# Install nodeenv with the version provided by edx-platform
|
|
151
158
|
# https://github.com/openedx/edx-platform/blob/master/requirements/edx/assets.txt
|
|
152
159
|
RUN $PIP_COMMAND install nodeenv==1.9.1
|
|
153
|
-
RUN nodeenv /openedx/nodeenv --node=24.
|
|
160
|
+
RUN nodeenv /openedx/nodeenv --node=24.22.1 --prebuilt
|
|
154
161
|
|
|
155
162
|
# Install nodejs requirements
|
|
156
163
|
ARG NPM_REGISTRY={{ NPM_REGISTRY }}
|
|
@@ -293,6 +300,9 @@ USER app
|
|
|
293
300
|
# Install dev python requirements
|
|
294
301
|
RUN --mount=type=cache,target=/openedx/.cache/pip,sharing=shared \
|
|
295
302
|
$PIP_COMMAND install -r requirements/edx/development.txt
|
|
303
|
+
# development.txt pins the old certifi again, so upgrade it one more time
|
|
304
|
+
RUN --mount=type=cache,target=/openedx/.cache/pip,sharing=shared \
|
|
305
|
+
$PIP_COMMAND install "certifi>=2026.10.19"
|
|
296
306
|
# https://pypi.org/project/ipdb/
|
|
297
307
|
# https://pypi.org/project/ipython (>=Python 3.10 started with 8.20)
|
|
298
308
|
RUN --mount=type=cache,target=/openedx/.cache/pip,sharing=shared \
|
|
@@ -15,7 +15,7 @@ DOCKER_REGISTRY: "docker.io/"
|
|
|
15
15
|
DOCKER_IMAGE_OPENEDX: "{{ DOCKER_REGISTRY }}overhangio/openedx:{{ TUTOR_VERSION }}"
|
|
16
16
|
DOCKER_IMAGE_OPENEDX_DEV: "openedx-dev:{{ TUTOR_VERSION }}"
|
|
17
17
|
# https://hub.docker.com/_/caddy/tags
|
|
18
|
-
DOCKER_IMAGE_CADDY: "docker.io/caddy:2.11.
|
|
18
|
+
DOCKER_IMAGE_CADDY: "docker.io/caddy:2.11.7"
|
|
19
19
|
# https://hub.docker.com/r/getmeili/meilisearch/tags
|
|
20
20
|
DOCKER_IMAGE_MEILISEARCH: "docker.io/getmeili/meilisearch:v1.36.0"
|
|
21
21
|
# https://hub.docker.com/_/mongo/tags
|
|
@@ -16,6 +16,12 @@ echo "MySQL is up and running"
|
|
|
16
16
|
|
|
17
17
|
# edx-platform database
|
|
18
18
|
mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "CREATE DATABASE IF NOT EXISTS {{ OPENEDX_MYSQL_DATABASE }};"
|
|
19
|
-
|
|
19
|
+
# This command may fail if the specified user has created a custom view, such
|
|
20
|
+
# as is done in the enterprise app.
|
|
21
|
+
#
|
|
22
|
+
# Yes, even 'if not exists' does not prevent this. :/
|
|
23
|
+
# https://bugs.mysql.com/bug.php?id=107139
|
|
24
|
+
mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "CREATE USER IF NOT EXISTS '{{ OPENEDX_MYSQL_USERNAME }}';" || true
|
|
25
|
+
# If the user truly doesn't exist, we'll get an error here.
|
|
20
26
|
mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "ALTER USER '{{ OPENEDX_MYSQL_USERNAME }}'@'%' IDENTIFIED BY '{{ OPENEDX_MYSQL_PASSWORD }}';"
|
|
21
27
|
mysql -u {{ MYSQL_ROOT_USERNAME }} --password="{{ MYSQL_ROOT_PASSWORD }}" --host "{{ MYSQL_HOST }}" --port {{ MYSQL_PORT }} -e "GRANT ALL ON {{ OPENEDX_MYSQL_DATABASE }}.* TO '{{ OPENEDX_MYSQL_USERNAME }}'@'%';"
|
|
@@ -27,6 +27,8 @@ services:
|
|
|
27
27
|
- ../apps/openedx/settings/cms:/openedx/edx-platform/cms/envs/tutor:roz
|
|
28
28
|
- ../apps/openedx/config:/openedx/config:roz
|
|
29
29
|
- ../../data/lms-job:/openedx/data:z
|
|
30
|
+
- ../../data/openedx-media:/openedx/media:z
|
|
31
|
+
- ../../data/openedx-media-private:/openedx/media-private:z
|
|
30
32
|
{%- for mount in iter_mounts(MOUNTS, "openedx", "lms-job") %}
|
|
31
33
|
- {{ mount }}:z
|
|
32
34
|
{%- endfor %}
|
|
@@ -42,6 +44,8 @@ services:
|
|
|
42
44
|
- ../apps/openedx/settings/cms:/openedx/edx-platform/cms/envs/tutor:roz
|
|
43
45
|
- ../apps/openedx/config:/openedx/config:roz
|
|
44
46
|
- ../../data/cms-job:/openedx/data:z
|
|
47
|
+
- ../../data/openedx-media:/openedx/media:z
|
|
48
|
+
- ../../data/openedx-media-private:/openedx/media-private:z
|
|
45
49
|
{%- for mount in iter_mounts(MOUNTS, "openedx", "cms-job") %}
|
|
46
50
|
- {{ mount }}:z
|
|
47
51
|
{%- endfor %}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|