e2xauthoring 0.2.0.dev1__tar.gz → 0.2.0.dev2__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.
Files changed (80) hide show
  1. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/PKG-INFO +1 -1
  2. e2xauthoring-0.2.0.dev2/e2xauthoring/__version__.py +1 -0
  3. e2xauthoring-0.2.0.dev2/e2xauthoring/app/handlers/apihandlers.py +129 -0
  4. e2xauthoring-0.2.0.dev2/e2xauthoring/app/handlers/base.py +102 -0
  5. e2xauthoring-0.2.0.dev2/e2xauthoring/app/templates/authoring/asset-manifest.json +10 -0
  6. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/app/templates/authoring/index.html +1 -1
  7. e2xauthoring-0.2.0.dev2/e2xauthoring/app/templates/authoring/static/js/main.1e6f65c1.js +3 -0
  8. e2xauthoring-0.2.0.dev2/e2xauthoring/app/templates/authoring/static/js/main.1e6f65c1.js.map +1 -0
  9. e2xauthoring-0.2.0.dev2/e2xauthoring/managers/__init__.py +17 -0
  10. e2xauthoring-0.2.0.dev1/e2xauthoring/models/assignmentmodel.py → e2xauthoring-0.2.0.dev2/e2xauthoring/managers/assignmentmanager.py +7 -7
  11. e2xauthoring-0.2.0.dev1/e2xauthoring/models/managers/manager.py → e2xauthoring-0.2.0.dev2/e2xauthoring/managers/base.py +19 -1
  12. e2xauthoring-0.2.0.dev2/e2xauthoring/managers/dataclasses/__init__.py +49 -0
  13. e2xauthoring-0.2.0.dev1/e2xauthoring/models/presetmodel.py → e2xauthoring-0.2.0.dev2/e2xauthoring/managers/presetmanager.py +11 -5
  14. e2xauthoring-0.2.0.dev2/e2xauthoring/managers/taskmanager.py +167 -0
  15. e2xauthoring-0.2.0.dev2/e2xauthoring/managers/taskpoolmanager.py +66 -0
  16. e2xauthoring-0.2.0.dev2/e2xauthoring/managers/templatemanager.py +69 -0
  17. e2xauthoring-0.2.0.dev2/e2xauthoring/managers/worksheetmanager.py +50 -0
  18. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/preprocessors/addtaskheader.py +1 -1
  19. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/preprocessors/copyfiles.py +5 -4
  20. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/preprocessors/copynotebooks.py +6 -5
  21. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/preprocessors/filltemplate.py +2 -0
  22. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/preprocessors/makeexercise.py +9 -2
  23. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/package-lock.json +24 -6
  24. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/package.json +1 -1
  25. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/pyproject.toml +1 -1
  26. e2xauthoring-0.2.0.dev1/e2xauthoring/__version__.py +0 -1
  27. e2xauthoring-0.2.0.dev1/e2xauthoring/app/handlers/apihandlers.py +0 -272
  28. e2xauthoring-0.2.0.dev1/e2xauthoring/app/handlers/base.py +0 -41
  29. e2xauthoring-0.2.0.dev1/e2xauthoring/app/templates/authoring/asset-manifest.json +0 -10
  30. e2xauthoring-0.2.0.dev1/e2xauthoring/app/templates/authoring/static/js/main.fe9bcd55.js +0 -3
  31. e2xauthoring-0.2.0.dev1/e2xauthoring/app/templates/authoring/static/js/main.fe9bcd55.js.map +0 -1
  32. e2xauthoring-0.2.0.dev1/e2xauthoring/models/__init__.py +0 -15
  33. e2xauthoring-0.2.0.dev1/e2xauthoring/models/basemodel.py +0 -20
  34. e2xauthoring-0.2.0.dev1/e2xauthoring/models/dataclasses/__init__.py +0 -28
  35. e2xauthoring-0.2.0.dev1/e2xauthoring/models/dataclasses/message.py +0 -13
  36. e2xauthoring-0.2.0.dev1/e2xauthoring/models/dataclasses/template.py +0 -6
  37. e2xauthoring-0.2.0.dev1/e2xauthoring/models/exercisemodel.py +0 -44
  38. e2xauthoring-0.2.0.dev1/e2xauthoring/models/lister/lister.py +0 -27
  39. e2xauthoring-0.2.0.dev1/e2xauthoring/models/lister/taskpoollister.py +0 -33
  40. e2xauthoring-0.2.0.dev1/e2xauthoring/models/lister/templatelister.py +0 -17
  41. e2xauthoring-0.2.0.dev1/e2xauthoring/models/managers/taskmanager.py +0 -123
  42. e2xauthoring-0.2.0.dev1/e2xauthoring/models/managers/taskpoolmanager.py +0 -63
  43. e2xauthoring-0.2.0.dev1/e2xauthoring/models/managers/templatemanager.py +0 -50
  44. e2xauthoring-0.2.0.dev1/e2xauthoring/models/taskmodel.py +0 -186
  45. e2xauthoring-0.2.0.dev1/e2xauthoring/models/taskpoolmodel.py +0 -125
  46. e2xauthoring-0.2.0.dev1/e2xauthoring/models/templatemodel.py +0 -67
  47. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/.github/workflows/sonarcloud.yml +0 -0
  48. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/.gitignore +0 -0
  49. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/.pre-commit-config.yaml +0 -0
  50. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/LICENSE +0 -0
  51. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/MANIFEST.in +0 -0
  52. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/README.md +0 -0
  53. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/__init__.py +0 -0
  54. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/app/__init__.py +0 -0
  55. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/app/authoring.py +0 -0
  56. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/app/handlers/handlers.py +0 -0
  57. /e2xauthoring-0.2.0.dev1/e2xauthoring/app/templates/authoring/static/js/main.fe9bcd55.js.LICENSE.txt → /e2xauthoring-0.2.0.dev2/e2xauthoring/app/templates/authoring/static/js/main.1e6f65c1.js.LICENSE.txt +0 -0
  58. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/assets/.gitignore +0 -0
  59. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/converters/__init__.py +0 -0
  60. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/converters/converter.py +0 -0
  61. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/converters/generateexercise.py +0 -0
  62. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/questions/Code (Autograded).ipynb +0 -0
  63. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/questions/Code (Manual).ipynb +0 -0
  64. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/questions/Diagram.ipynb +0 -0
  65. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/questions/Freetext.ipynb +0 -0
  66. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/questions/Multiple Choice.ipynb +0 -0
  67. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/questions/Single Choice.ipynb +0 -0
  68. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/questions/Upload Files.ipynb +0 -0
  69. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/template/Footer.ipynb +0 -0
  70. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/template/Group Info.ipynb +0 -0
  71. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/template/Header.ipynb +0 -0
  72. {e2xauthoring-0.2.0.dev1/e2xauthoring/models → e2xauthoring-0.2.0.dev2/e2xauthoring/managers}/presets/template/Student Info.ipynb +0 -0
  73. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/preprocessors/__init__.py +0 -0
  74. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/preprocessors/generatetaskids.py +0 -0
  75. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/preprocessors/preprocessor.py +0 -0
  76. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/preprocessors/removeexercise.py +0 -0
  77. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/utils/__init__.py +0 -0
  78. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/utils/gitutils.py +0 -0
  79. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/e2xauthoring/utils/notebookvariableextractor.py +0 -0
  80. {e2xauthoring-0.2.0.dev1 → e2xauthoring-0.2.0.dev2}/lerna.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: e2xauthoring
3
- Version: 0.2.0.dev1
3
+ Version: 0.2.0.dev2
4
4
  Summary: Authoring app for e2xgrader
5
5
  Project-URL: Source, https://github.com/Digiklausur/e2xauthoring
6
6
  Author-email: Tim Metzler <tim.metzler@h-brs.de>
@@ -0,0 +1 @@
1
+ __version__ = "0.2.0-dev2"
@@ -0,0 +1,129 @@
1
+ import json
2
+
3
+ from e2xcore.handlers import E2xApiHandler
4
+ from e2xcore.utils import urljoin
5
+ from jupyter_client.kernelspec import KernelSpecManager
6
+ from nbgrader.server_extensions.formgrader.base import check_xsrf
7
+ from tornado import web
8
+
9
+ from ...managers import (
10
+ AssignmentManager,
11
+ PresetManager,
12
+ TaskManager,
13
+ TaskPoolManager,
14
+ TemplateManager,
15
+ WorksheetManager,
16
+ )
17
+ from ...utils.gitutils import get_author, set_author
18
+ from .base import ApiManageHandler
19
+
20
+
21
+ class KernelSpecHandler(E2xApiHandler):
22
+ @web.authenticated
23
+ @check_xsrf
24
+ def get(self):
25
+ self.write(json.dumps(KernelSpecManager().get_all_specs()))
26
+
27
+
28
+ class GitAuthorHandler(E2xApiHandler):
29
+ @web.authenticated
30
+ @check_xsrf
31
+ def get(self):
32
+ self.write(json.dumps(get_author()))
33
+
34
+ @web.authenticated
35
+ @check_xsrf
36
+ def post(self):
37
+ data = self.get_json_body()
38
+ name = data.get("name")
39
+ email = data.get("email")
40
+ self.write(json.dumps(set_author(name=name, email=email)))
41
+
42
+
43
+ api_url = urljoin("e2x", "authoring", "api")
44
+ name_regex = r"(?P<name>[^/]+)"
45
+ assignment_regex = r"(?P<assignment>[^/]+)"
46
+ default_handlers = [
47
+ (
48
+ urljoin(api_url, "assignments", "?"),
49
+ ApiManageHandler,
50
+ dict(
51
+ manager_cls=AssignmentManager,
52
+ actions=dict(
53
+ get=dict(actions=["list"]),
54
+ ),
55
+ ),
56
+ ),
57
+ (
58
+ urljoin(api_url, "worksheets", "?"),
59
+ ApiManageHandler,
60
+ dict(
61
+ manager_cls=WorksheetManager,
62
+ actions=dict(
63
+ get=dict(actions=["get", "list"]),
64
+ delete=dict(default="remove", actions=["remove"]),
65
+ post=dict(default="create", actions=["create"]),
66
+ ),
67
+ ),
68
+ ),
69
+ (
70
+ urljoin(api_url, "tasks", "?"),
71
+ ApiManageHandler,
72
+ dict(
73
+ manager_cls=TaskManager,
74
+ actions=dict(
75
+ delete=dict(default="remove", actions=["remove"]),
76
+ get=dict(
77
+ default="get", actions=["get", "list", "list_all", "git_diff"]
78
+ ),
79
+ post=dict(default="create", actions=["create"]),
80
+ put=dict(actions=["copy", "rename", "commit"]),
81
+ ),
82
+ ),
83
+ ),
84
+ (
85
+ urljoin(api_url, "templates", "?"),
86
+ ApiManageHandler,
87
+ dict(
88
+ manager_cls=TemplateManager,
89
+ actions=dict(
90
+ delete=dict(default="remove", actions=["remove"]),
91
+ get=dict(default="get", actions=["get", "list", "list_variables"]),
92
+ post=dict(default="create", actions=["create"]),
93
+ put=dict(actions=["copy", "rename"]),
94
+ ),
95
+ ),
96
+ ),
97
+ (
98
+ urljoin(api_url, "pools", "?"),
99
+ ApiManageHandler,
100
+ dict(
101
+ manager_cls=TaskPoolManager,
102
+ actions=dict(
103
+ delete=dict(default="remove", actions=["remove"]),
104
+ get=dict(default="get", actions=["get", "list"]),
105
+ post=dict(default="create", actions=["create"]),
106
+ put=dict(actions=["copy", "rename", "turn_into_repository"]),
107
+ ),
108
+ ),
109
+ ),
110
+ (
111
+ urljoin(api_url, "presets", "?"),
112
+ ApiManageHandler,
113
+ dict(
114
+ manager_cls=PresetManager,
115
+ actions=dict(
116
+ get=dict(
117
+ actions=[
118
+ "list_question_presets",
119
+ "list_template_presets",
120
+ "get_question_preset",
121
+ "get_template_preset",
122
+ ]
123
+ )
124
+ ),
125
+ ),
126
+ ),
127
+ (urljoin(api_url, "kernelspec"), KernelSpecHandler),
128
+ (urljoin(api_url, "git", "author"), GitAuthorHandler),
129
+ ]
@@ -0,0 +1,102 @@
1
+ import inspect
2
+ from typing import List
3
+
4
+ from e2xcore.handlers import E2xApiHandler
5
+ from nbgrader.server_extensions.formgrader.base import check_xsrf
6
+ from tornado import web
7
+
8
+ from e2xauthoring.managers.dataclasses import ErrorMessage, SuccessMessage
9
+
10
+
11
+ def status_msg(method):
12
+ """Decorates a method of a BaseApiManager
13
+ Wraps the response in a status message (ErrorMessage or SuccessMessage)
14
+ and catches exceptions.
15
+
16
+ Args:
17
+ method: The method to decorate
18
+ """
19
+
20
+ def wrapper(*args, **kwargs):
21
+ try:
22
+ res = method(*args, **kwargs)
23
+ return SuccessMessage(data=res)
24
+ except Exception as e:
25
+ return ErrorMessage(error=getattr(e, "message", str(e)))
26
+
27
+ return wrapper
28
+
29
+
30
+ class ApiManageHandler(E2xApiHandler):
31
+ def initialize(self, manager_cls, actions) -> None:
32
+ self.__manager = manager_cls(self.coursedir)
33
+ self.__allowed_actions = {
34
+ request_type: dict(default=None, actions=[])
35
+ for request_type in ["delete", "get", "post", "put"]
36
+ }
37
+ self.set_allowed_actions(actions)
38
+
39
+ def set_allowed_actions(self, allowed_actions):
40
+ for request_type, action_dict in self.__allowed_actions.items():
41
+ if request_type in allowed_actions:
42
+ actions = allowed_actions[request_type].get("actions", [])
43
+ for action in actions:
44
+ assert hasattr(
45
+ self.__manager, action
46
+ ), f"The manager class does not provide an action called {action}."
47
+ action_dict["default"] = allowed_actions[request_type].get(
48
+ "default", None
49
+ )
50
+ action_dict["actions"].extend(actions)
51
+
52
+ def extract_arguments(self, method: str):
53
+ params = dict()
54
+ json_body = self.get_json_body() or dict()
55
+ for arg in inspect.signature(method).parameters.keys():
56
+ argument = self.get_argument(name=arg, default=None)
57
+ if argument is None:
58
+ argument = json_body.get(arg, None)
59
+ params[arg] = argument
60
+ return params
61
+
62
+ def perform_action(self, action: str, allowed_actions: List[str]):
63
+ assert (
64
+ action is not None and action in allowed_actions
65
+ ), f"Action {action} is not a valid action."
66
+ method = getattr(self.__manager, action)
67
+ arguments = self.extract_arguments(method)
68
+ return method(**arguments)
69
+
70
+ @status_msg
71
+ def handle_request(self, request_type: str):
72
+ action = self.get_argument(
73
+ "action", default=None # self.__allowed_actions[request_type]["default"]
74
+ )
75
+ if action is None:
76
+ action = (self.get_json_body() or dict()).get(
77
+ "action", self.__allowed_actions[request_type]["default"]
78
+ )
79
+
80
+ return self.perform_action(
81
+ action, self.__allowed_actions[request_type]["actions"]
82
+ )
83
+
84
+ @web.authenticated
85
+ @check_xsrf
86
+ def get(self):
87
+ self.finish(self.handle_request("get").json())
88
+
89
+ @web.authenticated
90
+ @check_xsrf
91
+ def delete(self):
92
+ self.finish(self.handle_request("delete").json())
93
+
94
+ @web.authenticated
95
+ @check_xsrf
96
+ def put(self):
97
+ self.finish(self.handle_request("put").json())
98
+
99
+ @web.authenticated
100
+ @check_xsrf
101
+ def post(self):
102
+ self.finish(self.handle_request("post").json())
@@ -0,0 +1,10 @@
1
+ {
2
+ "files": {
3
+ "main.js": "/e2x/authoring/static/js/main.1e6f65c1.js",
4
+ "index.html": "/e2x/authoring/index.html",
5
+ "main.1e6f65c1.js.map": "/e2x/authoring/static/js/main.1e6f65c1.js.map"
6
+ },
7
+ "entrypoints": [
8
+ "static/js/main.1e6f65c1.js"
9
+ ]
10
+ }
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>e²xgrader - Authoring</title><script type="text/javascript">window.base_url="{{ base_url }}",window.url_prefix="{{ url_prefix }}",window.webpackstuff="/e2x/authoring/static/js/main.fe9bcd55.js"</script><script defer="defer" src="{{base_url}}/e2x/authoring/static/js/main.fe9bcd55.js"></script>{%- block head -%} {%- endblock -%}</head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>e²xgrader - Authoring</title><script type="text/javascript">window.base_url="{{ base_url }}",window.url_prefix="{{ url_prefix }}",window.webpackstuff="/e2x/authoring/static/js/main.1e6f65c1.js"</script><script defer="defer" src="{{base_url}}/e2x/authoring/static/js/main.1e6f65c1.js"></script>{%- block head -%} {%- endblock -%}</head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>