Coverage for e2xgrader/utils/mode.py: 100%
58 statements
« prev ^ index » next coverage.py v7.4.2, created at 2024-03-14 13:22 +0100
« prev ^ index » next coverage.py v7.4.2, created at 2024-03-14 13:22 +0100
1import os
2from enum import Enum
3from typing import Dict
5from jupyter_core.paths import jupyter_config_path
7from .. import _jupyter_server_extension_paths
8from ..extensions.utils import discover_nbextensions, get_notebook_config_manager
11class E2xGraderMode(Enum):
12 TEACHER = "teacher"
13 STUDENT = "student"
14 STUDENT_EXAM = "student_exam"
15 INVALID = "invalid"
16 INACTIVE = "inactive"
19def get_nbextension_config() -> Dict[str, Dict[str, bool]]:
20 """
21 Get the configuration for nbextensions.
23 Returns:
24 A dictionary containing the configuration for nbextensions.
25 The dictionary has the following structure:
26 {
27 'tree': {
28 'nbextension_name': True/False,
29 ...
30 },
31 'notebook': {
32 'nbextension_name': True/False,
33 ...
34 }
35 }
36 """
37 config = dict(tree=dict(), notebook=dict())
38 for path in jupyter_config_path():
39 config_path = os.path.join(path, "nbconfig")
40 contextmanager = get_notebook_config_manager()(config_dir=config_path)
41 for key in config:
42 config[key].update(contextmanager.get(key))
43 return config
46def get_serverextension_config() -> Dict[str, bool]:
47 """
48 Retrieves the server extension configuration from the Jupyter notebook configuration files.
50 Returns:
51 A dictionary containing the server extension configuration, where the keys are the
52 extension names and the values are boolean values indicating whether the extension
53 is enabled or not.
54 """
55 config = dict()
56 for path in jupyter_config_path():
57 contextmanager = get_notebook_config_manager()(config_dir=path)
58 config.update(contextmanager.get("jupyter_notebook_config"))
59 return config.get("NotebookApp", dict()).get("nbserver_extensions", dict())
62def infer_nbextension_mode() -> str:
63 """
64 Infer the active mode for the nbextension based on the current configuration.
66 Returns:
67 str: The active mode for the nbextension.
69 Raises:
70 ValueError: If more than one mode is active or if tree and notebook extensions don't match.
71 """
72 config = get_nbextension_config()
73 modes = [
74 E2xGraderMode.TEACHER.value,
75 E2xGraderMode.STUDENT_EXAM.value,
76 E2xGraderMode.STUDENT.value,
77 ]
78 is_active = dict(tree=[], notebook=[])
79 for mode in modes:
80 for extension in discover_nbextensions(mode):
81 if (
82 config[extension["section"]]
83 .get("load_extensions", dict())
84 .get(extension["require"], False)
85 ):
86 is_active[extension["section"]].append(mode)
88 if set(is_active["tree"]) == set(is_active["notebook"]):
89 if len(is_active["tree"]) == 1:
90 return is_active["tree"][0]
91 elif len(is_active["tree"]) == 0:
92 return E2xGraderMode.INACTIVE.value
93 raise ValueError(
94 "More than one mode is active or tree and notebook extensions don't match\n"
95 f"The current config is {config}"
96 )
99def infer_serverextension_mode() -> str:
100 """
101 Infer the server extension mode based on the configuration.
103 Returns:
104 str: The server extension mode. Possible values are:
105 - "None" if no server extension is active.
106 - The name of the active server extension if only one is active.
108 Raises:
109 ValueError: If more than one server extension is active.
110 """
111 config = get_serverextension_config()
112 active = []
113 for extension in _jupyter_server_extension_paths():
114 is_active = config.get(extension["module"], False)
115 if is_active:
116 active.append(extension["module"].split(".")[-1])
117 if len(active) == 0:
118 return E2xGraderMode.INACTIVE.value
119 elif len(active) == 1:
120 return active[0]
121 raise ValueError("More than one mode is active" f"The current config is {config}")
124def infer_e2xgrader_mode() -> str:
125 """
126 Infer the mode of e2xgrader.
128 Returns:
129 str: The mode of e2xgrader.
131 Raises:
132 ValueError: If the nbextension mode and serverextension mode do not match.
133 """
134 nbextension_mode = infer_nbextension_mode()
135 serverextension_mode = infer_serverextension_mode()
136 if nbextension_mode == serverextension_mode:
137 return nbextension_mode
138 raise ValueError(
139 "The nbextension and serverextension mode does not match"
140 f"nbextension mode is {nbextension_mode}, serverextension_mode is {serverextension_mode}"
141 )