PyKubeGrader 0.1.12__py3-none-any.whl → 0.1.13__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- {PyKubeGrader-0.1.12.dist-info → PyKubeGrader-0.1.13.dist-info}/METADATA +1 -1
- {PyKubeGrader-0.1.12.dist-info → PyKubeGrader-0.1.13.dist-info}/RECORD +10 -10
- pykubegrader/build/api_notebook_builder.py +9 -7
- pykubegrader/build/build_folder.py +2 -0
- pykubegrader/initialize.py +75 -34
- pykubegrader/telemetry.py +3 -3
- {PyKubeGrader-0.1.12.dist-info → PyKubeGrader-0.1.13.dist-info}/LICENSE.txt +0 -0
- {PyKubeGrader-0.1.12.dist-info → PyKubeGrader-0.1.13.dist-info}/WHEEL +0 -0
- {PyKubeGrader-0.1.12.dist-info → PyKubeGrader-0.1.13.dist-info}/entry_points.txt +0 -0
- {PyKubeGrader-0.1.12.dist-info → PyKubeGrader-0.1.13.dist-info}/top_level.txt +0 -0
@@ -1,10 +1,10 @@
|
|
1
1
|
pykubegrader/__init__.py,sha256=AoAkdfIjDDZGWLlsIRENNq06L9h46kDGBIE8vRmsCfg,311
|
2
|
-
pykubegrader/initialize.py,sha256=
|
3
|
-
pykubegrader/telemetry.py,sha256=
|
2
|
+
pykubegrader/initialize.py,sha256=3mz-Zv1mlmHTRNktObmOIbBRsipg16JX6wg9-_vFQe4,3043
|
3
|
+
pykubegrader/telemetry.py,sha256=4-YdfAepiKO8y9TFoU_ktI64iFTIuKK3RcAXIz0KmP0,3972
|
4
4
|
pykubegrader/utils.py,sha256=dKw6SyRYU3DWRgD3xER7wq-C9e1daWPkqr901LpcwiQ,642
|
5
5
|
pykubegrader/validate.py,sha256=F0SuGGj236rFr0HFLhuF1R1whrs2vhbDrG5qu_0PojQ,10707
|
6
|
-
pykubegrader/build/api_notebook_builder.py,sha256=
|
7
|
-
pykubegrader/build/build_folder.py,sha256=
|
6
|
+
pykubegrader/build/api_notebook_builder.py,sha256=DPxjBhqUmSVF3PVhvgBbZR2BaCpp6Zt9fDUFyR_CAX0,19126
|
7
|
+
pykubegrader/build/build_folder.py,sha256=Iw20V65Eggli4noS4WaNJJcYmo185A01ofxQBtODYec,64366
|
8
8
|
pykubegrader/widgets/__init__.py,sha256=s3ky3eJDa1RedFVdpKxmqv6mHBYpOSL9Z6qThSH9cbs,303
|
9
9
|
pykubegrader/widgets/multiple_choice.py,sha256=NjD3-uXSnibpUQ0mO3hRp_O-rynFyl0Dz6IXE4tnCRI,2078
|
10
10
|
pykubegrader/widgets/reading_question.py,sha256=y30_swHwzH8LrT8deWTnxctAAmR8BSxTlXAqMgUrAT4,3031
|
@@ -17,9 +17,9 @@ pykubegrader/widgets_base/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-
|
|
17
17
|
pykubegrader/widgets_base/multi_select.py,sha256=u50IOhYxC_S_gq31VnFPLdbNajk_SUWhaqlMSJxhqVQ,3439
|
18
18
|
pykubegrader/widgets_base/reading.py,sha256=4uTLmlPzCwxVzufFhPjM7W19uMGguRb6y4eAV3x-zAc,5314
|
19
19
|
pykubegrader/widgets_base/select.py,sha256=h1S5StcbX8S-Wiyga4fVDhPbVvRxffwaqyVbiiuInRs,2743
|
20
|
-
PyKubeGrader-0.1.
|
21
|
-
PyKubeGrader-0.1.
|
22
|
-
PyKubeGrader-0.1.
|
23
|
-
PyKubeGrader-0.1.
|
24
|
-
PyKubeGrader-0.1.
|
25
|
-
PyKubeGrader-0.1.
|
20
|
+
PyKubeGrader-0.1.13.dist-info/LICENSE.txt,sha256=YTp-Ewc8Kems8PJEE27KnBPFnZSxoWvSg7nnknzPyYw,1546
|
21
|
+
PyKubeGrader-0.1.13.dist-info/METADATA,sha256=GMuh1zsIM9Ft5nioXmqsLiCT9tQqdCerweyPoiq8cig,2665
|
22
|
+
PyKubeGrader-0.1.13.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
23
|
+
PyKubeGrader-0.1.13.dist-info/entry_points.txt,sha256=Kd4Bh-i3hc4qlnLU1p0nc8yPw9cC5AQGOtkk2eLGnQw,78
|
24
|
+
PyKubeGrader-0.1.13.dist-info/top_level.txt,sha256=e550Klfze6higFxER1V62fnGOcIgiKRbsrl9CC4UdtQ,13
|
25
|
+
PyKubeGrader-0.1.13.dist-info/RECORD,,
|
@@ -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
|
-
|
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
|
-
[
|
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
|
-
"
|
207
|
+
" submit_question,\n",
|
206
208
|
" telemetry,\n",
|
207
209
|
" update_responses,\n",
|
208
210
|
")\n",
|
pykubegrader/initialize.py
CHANGED
@@ -1,65 +1,106 @@
|
|
1
|
-
import json
|
2
1
|
import os
|
3
|
-
|
2
|
+
import shutil
|
3
|
+
from pathlib import Path
|
4
4
|
|
5
5
|
import panel as pn
|
6
|
-
from IPython import get_ipython
|
7
6
|
import requests
|
8
|
-
from
|
7
|
+
from IPython import get_ipython
|
8
|
+
|
9
|
+
from .telemetry import ensure_responses, telemetry, update_responses
|
9
10
|
|
10
11
|
|
11
12
|
def initialize_assignment(
|
12
13
|
name: str,
|
13
|
-
|
14
|
-
|
15
|
-
) ->
|
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
|
+
|
16
32
|
ipython = get_ipython()
|
17
33
|
if ipython is None:
|
18
|
-
|
19
|
-
return
|
34
|
+
raise Exception("Setup unsuccessful. Are you in a Jupyter environment?")
|
20
35
|
|
21
36
|
try:
|
37
|
+
move_dotfiles()
|
22
38
|
ipython.events.register("pre_run_cell", telemetry)
|
23
|
-
except
|
24
|
-
|
25
|
-
return
|
39
|
+
except Exception as e:
|
40
|
+
raise Exception(f"Failed to register telemetry: {e}")
|
26
41
|
|
27
42
|
jhub_user = os.getenv("JUPYTERHUB_USER")
|
28
43
|
if jhub_user is None:
|
29
|
-
|
30
|
-
return
|
44
|
+
raise Exception("Setup unsuccessful. Are you on JupyterHub?")
|
31
45
|
|
32
46
|
try:
|
33
47
|
seed = hash(jhub_user) % 1000
|
34
48
|
update_responses(key="seed", value=seed)
|
49
|
+
|
35
50
|
update_responses(key="assignment", value=name)
|
36
51
|
update_responses(key="jhub_user", value=jhub_user)
|
37
52
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
# extract responses
|
43
|
-
responses = ensure_responses()
|
53
|
+
responses = ensure_responses()
|
54
|
+
# TODO: Add more checks here?
|
55
|
+
assert isinstance(responses.get("seed"), int), "Seed not set"
|
44
56
|
|
45
|
-
|
46
|
-
assert isinstance(responses.get("seed"), int), "valid seed not found in responses"
|
57
|
+
pn.extension(silent=True)
|
47
58
|
|
48
|
-
|
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}")
|
49
69
|
|
70
|
+
print("Assignment successfully initialized")
|
50
71
|
if verbose:
|
51
|
-
print("Assignment successfully initialized")
|
52
72
|
print(f"Assignment: {name}")
|
53
73
|
print(f"Username: {jhub_user}")
|
54
74
|
|
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
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}")
|
pykubegrader/telemetry.py
CHANGED
@@ -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
|
122
|
+
def submit_question(
|
123
123
|
student_email: str,
|
124
124
|
term: str,
|
125
125
|
assignment: str,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|