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.
@@ -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,10 +1,10 @@
1
1
  pykubegrader/__init__.py,sha256=AoAkdfIjDDZGWLlsIRENNq06L9h46kDGBIE8vRmsCfg,311
2
- pykubegrader/initialize.py,sha256=5DiadyfFwFmqChAw8eKxryrlv0Va2ADD8JY4CJDxPAQ,1871
3
- pykubegrader/telemetry.py,sha256=4npUDOyGgT4_0SCXTIvHJJh6a0dlUbh1Sro1qTq1y0c,3940
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=G5wokv14Cr9cZQslM8_JN8e3-_z033G3IxTb9UjaJL0,19070
7
- pykubegrader/build/build_folder.py,sha256=yUAkxBebZMDCWEt2pF1rCjohcLxuKTW2-PJuZattqR4,64364
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.12.dist-info/LICENSE.txt,sha256=YTp-Ewc8Kems8PJEE27KnBPFnZSxoWvSg7nnknzPyYw,1546
21
- PyKubeGrader-0.1.12.dist-info/METADATA,sha256=5byY9ZTimHC0GxRdmkv62YKUfj2IaCqVTpJK5vis9qA,2665
22
- PyKubeGrader-0.1.12.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
23
- PyKubeGrader-0.1.12.dist-info/entry_points.txt,sha256=Kd4Bh-i3hc4qlnLU1p0nc8yPw9cC5AQGOtkk2eLGnQw,78
24
- PyKubeGrader-0.1.12.dist-info/top_level.txt,sha256=e550Klfze6higFxER1V62fnGOcIgiKRbsrl9CC4UdtQ,13
25
- PyKubeGrader-0.1.12.dist-info/RECORD,,
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
- 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
 
@@ -1,65 +1,106 @@
1
- import json
2
1
  import os
3
- from typing import Optional
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 .telemetry import telemetry, update_responses, ensure_responses
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
- verbose: Optional[bool] = False,
14
- url: Optional[str] = "https://engr-131-api.eastus.cloudapp.azure.com/",
15
- ) -> None:
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
- print("Setup unsuccessful. Are you in a Jupyter environment?")
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 TypeError as e:
24
- print(f"Failed to register telemetry: {e}")
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
- print("Setup unsuccessful. Are you on JupyterHub?")
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
- except (TypeError, json.JSONDecodeError) as e:
39
- print(f"Failed to initialize assignment: {e}")
40
- return
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
- # TODO: Add more checks here??
46
- assert isinstance(responses.get("seed"), int), "valid seed not found in responses"
57
+ pn.extension(silent=True)
47
58
 
48
- pn.extension(silent=True)
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 submit_question_new(
122
+ def submit_question(
123
123
  student_email: str,
124
124
  term: str,
125
125
  assignment: str,