PyKubeGrader 0.1.12__tar.gz → 0.1.13__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. {pykubegrader-0.1.12/src/PyKubeGrader.egg-info → pykubegrader-0.1.13}/PKG-INFO +1 -1
  2. {pykubegrader-0.1.12 → pykubegrader-0.1.13/src/PyKubeGrader.egg-info}/PKG-INFO +1 -1
  3. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/build/api_notebook_builder.py +9 -7
  4. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/build/build_folder.py +2 -0
  5. pykubegrader-0.1.13/src/pykubegrader/initialize.py +106 -0
  6. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/telemetry.py +3 -3
  7. pykubegrader-0.1.12/src/pykubegrader/initialize.py +0 -65
  8. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/.coveragerc +0 -0
  9. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/.github/workflows/main.yml +0 -0
  10. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/.gitignore +0 -0
  11. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/.readthedocs.yml +0 -0
  12. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/AUTHORS.rst +0 -0
  13. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/CHANGELOG.rst +0 -0
  14. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/CONTRIBUTING.rst +0 -0
  15. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/LICENSE.txt +0 -0
  16. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/README.rst +0 -0
  17. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/Makefile +0 -0
  18. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/_static/Drexel_blue_Logo_square_Dark.png +0 -0
  19. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/_static/Drexel_blue_Logo_square_Light.png +0 -0
  20. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/_static/custom.css +0 -0
  21. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/authors.rst +0 -0
  22. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/changelog.rst +0 -0
  23. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/conf.py +0 -0
  24. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/contributing.rst +0 -0
  25. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/index.rst +0 -0
  26. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/license.rst +0 -0
  27. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/readme.rst +0 -0
  28. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/docs/requirements.txt +0 -0
  29. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/examples/.responses.json +0 -0
  30. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/examples/true_false.ipynb +0 -0
  31. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/pyproject.toml +0 -0
  32. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/setup.cfg +0 -0
  33. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/setup.py +0 -0
  34. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/PyKubeGrader.egg-info/SOURCES.txt +0 -0
  35. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/PyKubeGrader.egg-info/dependency_links.txt +0 -0
  36. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/PyKubeGrader.egg-info/entry_points.txt +0 -0
  37. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/PyKubeGrader.egg-info/not-zip-safe +0 -0
  38. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/PyKubeGrader.egg-info/requires.txt +0 -0
  39. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/PyKubeGrader.egg-info/top_level.txt +0 -0
  40. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/__init__.py +0 -0
  41. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/utils.py +0 -0
  42. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/validate.py +0 -0
  43. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets/__init__.py +0 -0
  44. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets/multiple_choice.py +0 -0
  45. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets/reading_question.py +0 -0
  46. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets/select_many.py +0 -0
  47. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets/student_info.py +0 -0
  48. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets/style.py +0 -0
  49. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets/true_false.py +0 -0
  50. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets/types_question.py +0 -0
  51. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets_base/__init__.py +0 -0
  52. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets_base/multi_select.py +0 -0
  53. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets_base/reading.py +0 -0
  54. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/src/pykubegrader/widgets_base/select.py +0 -0
  55. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/tests/conftest.py +0 -0
  56. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/tests/import_test.py +0 -0
  57. {pykubegrader-0.1.12 → pykubegrader-0.1.13}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyKubeGrader
3
- Version: 0.1.12
3
+ Version: 0.1.13
4
4
  Summary: Add a short description here!
5
5
  Home-page: https://github.com/pyscaffold/pyscaffold/
6
6
  Author: jagar2
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyKubeGrader
3
- Version: 0.1.12
3
+ Version: 0.1.13
4
4
  Summary: Add a short description here!
5
5
  Home-page: https://github.com/pyscaffold/pyscaffold/
6
6
  Author: jagar2
@@ -1,12 +1,12 @@
1
+ import ast
2
+ import json
3
+ import re
4
+ import shutil
1
5
  from dataclasses import dataclass
2
6
  from pathlib import Path
3
7
  from typing import Optional
4
- import json
8
+
5
9
  import nbformat
6
- import json
7
- import re
8
- import shutil
9
- import ast
10
10
 
11
11
 
12
12
  @dataclass
@@ -76,7 +76,9 @@ class FastAPINotebookBuilder:
76
76
  )
77
77
  updated_cell_source.extend(["earned_points += score\n"])
78
78
  updated_cell_source.extend(
79
- [f'log_variable(f"{{score}}, {{max_score}}", question_id)\n']
79
+ [
80
+ f'log_variable(f"{{score}}, {{max_score}}", question_id, "{self.filename.split(".")[0]}")\n'
81
+ ]
80
82
  )
81
83
  updated_cell_source.extend(
82
84
  ["os.environ['EARNED_POINTS'] = str(earned_points)\n"]
@@ -202,7 +204,7 @@ class FastAPINotebookBuilder:
202
204
  " ensure_responses,\n",
203
205
  " log_variable,\n",
204
206
  " score_question,\n",
205
- " submit_question_new,\n",
207
+ " submit_question,\n",
206
208
  " telemetry,\n",
207
209
  " update_responses,\n",
208
210
  ")\n",
@@ -8,7 +8,9 @@ import shutil
8
8
  import subprocess
9
9
  import sys
10
10
  from dataclasses import dataclass, field
11
+
11
12
  import nbformat
13
+
12
14
  from .api_notebook_builder import FastAPINotebookBuilder
13
15
 
14
16
 
@@ -0,0 +1,106 @@
1
+ import os
2
+ import shutil
3
+ from pathlib import Path
4
+
5
+ import panel as pn
6
+ import requests
7
+ from IPython import get_ipython
8
+
9
+ from .telemetry import ensure_responses, telemetry, update_responses
10
+
11
+
12
+ def initialize_assignment(
13
+ name: str,
14
+ url: str = "https://engr-131-api.eastus.cloudapp.azure.com/",
15
+ verbose: bool = False,
16
+ ) -> dict:
17
+ """
18
+ Initialize an assignment in a Jupyter environment.
19
+
20
+ Args:
21
+ name (str): The name of the assignment.
22
+ url (str): The URL of the API server.
23
+ verbose (bool): Whether to print detailed initialization information.
24
+
25
+ Returns:
26
+ dict: The responses dictionary after initialization.
27
+
28
+ Raises:
29
+ Exception: If the environment is unsupported or initialization fails.
30
+ """
31
+
32
+ ipython = get_ipython()
33
+ if ipython is None:
34
+ raise Exception("Setup unsuccessful. Are you in a Jupyter environment?")
35
+
36
+ try:
37
+ move_dotfiles()
38
+ ipython.events.register("pre_run_cell", telemetry)
39
+ except Exception as e:
40
+ raise Exception(f"Failed to register telemetry: {e}")
41
+
42
+ jhub_user = os.getenv("JUPYTERHUB_USER")
43
+ if jhub_user is None:
44
+ raise Exception("Setup unsuccessful. Are you on JupyterHub?")
45
+
46
+ try:
47
+ seed = hash(jhub_user) % 1000
48
+ update_responses(key="seed", value=seed)
49
+
50
+ update_responses(key="assignment", value=name)
51
+ update_responses(key="jhub_user", value=jhub_user)
52
+
53
+ responses = ensure_responses()
54
+ # TODO: Add more checks here?
55
+ assert isinstance(responses.get("seed"), int), "Seed not set"
56
+
57
+ pn.extension(silent=True)
58
+
59
+ # Check connection to API server
60
+ params = {"jhub_user": responses["jhub_user"]}
61
+ response = requests.get(url, params=params)
62
+ if verbose:
63
+ print(f"status code: {response.status_code}")
64
+ data = response.json()
65
+ for k, v in data.items():
66
+ print(f"{k}: {v}")
67
+ except Exception as e:
68
+ raise Exception(f"Failed to initialize assignment: {e}")
69
+
70
+ print("Assignment successfully initialized")
71
+ if verbose:
72
+ print(f"Assignment: {name}")
73
+ print(f"Username: {jhub_user}")
74
+
75
+ return responses
76
+
77
+
78
+ #
79
+ # Helper functions
80
+ #
81
+
82
+
83
+ def move_dotfiles():
84
+ """
85
+ Move essential dotfiles from a fixed source directory to the current working directory.
86
+
87
+ Raises:
88
+ FileNotFoundError: If a source file is missing.
89
+ Exception: If copying fails for any other reason.
90
+ """
91
+ source_dir = Path("/opt/dotfiles")
92
+ target_dir = Path.cwd()
93
+
94
+ files_to_copy = [".client_private_key.bin", ".server_public_key.bin"]
95
+
96
+ for file_name in files_to_copy:
97
+ source_file = source_dir / file_name
98
+ target_file = target_dir / file_name
99
+
100
+ if not source_file.exists():
101
+ raise FileNotFoundError(f"Key file not found: {source_file}")
102
+
103
+ try:
104
+ shutil.copy2(source_file, target_file)
105
+ except Exception as e:
106
+ raise Exception(f"Failed to copy {source_file} to {target_file}: {e}")
@@ -56,9 +56,9 @@ def log_encrypted(message: str) -> None:
56
56
  logging.info(f"Encrypted Output: {encrypted_b64}")
57
57
 
58
58
 
59
- def log_variable(value, info_type) -> None:
59
+ def log_variable(assignment_name, value, info_type) -> None:
60
60
  timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
61
- message = f"{info_type}, {value}, {timestamp}"
61
+ message = f"{info_type}, {value}, {timestamp}, {assignment_name}"
62
62
  log_encrypted(message)
63
63
 
64
64
 
@@ -119,7 +119,7 @@ def score_question(
119
119
  return res
120
120
 
121
121
 
122
- def submit_question_new(
122
+ def submit_question(
123
123
  student_email: str,
124
124
  term: str,
125
125
  assignment: str,
@@ -1,65 +0,0 @@
1
- import json
2
- import os
3
- from typing import Optional
4
-
5
- import panel as pn
6
- from IPython import get_ipython
7
- import requests
8
- from .telemetry import telemetry, update_responses, ensure_responses
9
-
10
-
11
- def initialize_assignment(
12
- name: str,
13
- verbose: Optional[bool] = False,
14
- url: Optional[str] = "https://engr-131-api.eastus.cloudapp.azure.com/",
15
- ) -> None:
16
- ipython = get_ipython()
17
- if ipython is None:
18
- print("Setup unsuccessful. Are you in a Jupyter environment?")
19
- return
20
-
21
- try:
22
- ipython.events.register("pre_run_cell", telemetry)
23
- except TypeError as e:
24
- print(f"Failed to register telemetry: {e}")
25
- return
26
-
27
- jhub_user = os.getenv("JUPYTERHUB_USER")
28
- if jhub_user is None:
29
- print("Setup unsuccessful. Are you on JupyterHub?")
30
- return
31
-
32
- try:
33
- seed = hash(jhub_user) % 1000
34
- update_responses(key="seed", value=seed)
35
- update_responses(key="assignment", value=name)
36
- update_responses(key="jhub_user", value=jhub_user)
37
-
38
- except (TypeError, json.JSONDecodeError) as e:
39
- print(f"Failed to initialize assignment: {e}")
40
- return
41
-
42
- # extract responses
43
- responses = ensure_responses()
44
-
45
- # TODO: Add more checks here??
46
- assert isinstance(responses.get("seed"), int), "valid seed not found in responses"
47
-
48
- pn.extension(silent=True)
49
-
50
- if verbose:
51
- print("Assignment successfully initialized")
52
- print(f"Assignment: {name}")
53
- print(f"Username: {jhub_user}")
54
-
55
- # Checks connectivity to the API
56
- params = {"jhub_user": responses["jhub_user"]}
57
- response = requests.get(url, params=params)
58
- if verbose:
59
- print(f"status code: {response.status_code}")
60
- data = response.json()
61
- for k, v in data.items():
62
- print(f"{k}: {v}")
63
-
64
- print("Assignment successfully initialized")
65
- return responses
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes