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

1import os 

2from enum import Enum 

3from typing import Dict 

4 

5from jupyter_core.paths import jupyter_config_path 

6 

7from .. import _jupyter_server_extension_paths 

8from ..extensions.utils import discover_nbextensions, get_notebook_config_manager 

9 

10 

11class E2xGraderMode(Enum): 

12 TEACHER = "teacher" 

13 STUDENT = "student" 

14 STUDENT_EXAM = "student_exam" 

15 INVALID = "invalid" 

16 INACTIVE = "inactive" 

17 

18 

19def get_nbextension_config() -> Dict[str, Dict[str, bool]]: 

20 """ 

21 Get the configuration for nbextensions. 

22 

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 

44 

45 

46def get_serverextension_config() -> Dict[str, bool]: 

47 """ 

48 Retrieves the server extension configuration from the Jupyter notebook configuration files. 

49 

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()) 

60 

61 

62def infer_nbextension_mode() -> str: 

63 """ 

64 Infer the active mode for the nbextension based on the current configuration. 

65 

66 Returns: 

67 str: The active mode for the nbextension. 

68 

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) 

87 

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 ) 

97 

98 

99def infer_serverextension_mode() -> str: 

100 """ 

101 Infer the server extension mode based on the configuration. 

102 

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. 

107 

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}") 

122 

123 

124def infer_e2xgrader_mode() -> str: 

125 """ 

126 Infer the mode of e2xgrader. 

127 

128 Returns: 

129 str: The mode of e2xgrader. 

130 

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 )