PyKubeGrader 0.2.5__py3-none-any.whl → 0.2.6__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.2.5
3
+ Version: 0.2.6
4
4
  Summary: Add a short description here!
5
5
  Home-page: https://github.com/pyscaffold/pyscaffold/
6
6
  Author: jagar2
@@ -1,16 +1,16 @@
1
1
  pykubegrader/__init__.py,sha256=AoAkdfIjDDZGWLlsIRENNq06L9h46kDGBIE8vRmsCfg,311
2
- pykubegrader/initialize.py,sha256=lQ80bB4LHDLJXFFl820_mNTFXvXpLT-rEAViBBsEPn0,3568
2
+ pykubegrader/initialize.py,sha256=DUen_B1cHFOmwiMpB_wkCqHIjvGChsu62-WiFkKa5Wo,3766
3
3
  pykubegrader/telemetry.py,sha256=h8PPrXWGFgPWCcrChJo2woqd_XIPMFfYcxgLJ0CWpH8,5360
4
4
  pykubegrader/utils.py,sha256=T3GYnLnTL9VXjTZNPr00sUgMgobQYsNTGwynMyXdvHk,696
5
5
  pykubegrader/validate.py,sha256=2KLSB3wfFZbBh1NGgmrOV073paKAgrQz4AgA6LmCIj4,11076
6
6
  pykubegrader/build/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
7
  pykubegrader/build/api_notebook_builder.py,sha256=FEaTj1fEsPAes7KNrPuhClEvKzLuOL3wG7Hgr7FQc-o,20083
8
- pykubegrader/build/build_folder.py,sha256=MyQ7ncPwiuTZ9PD7Q7al1n1bog4cugH1ew5DEC2NqNM,71700
8
+ pykubegrader/build/build_folder.py,sha256=g8yRRGmHxW_47WHpFPsH9tiuFgFrvcxBPJwjZyFMS_w,74895
9
9
  pykubegrader/build/clean_folder.py,sha256=8N0KyL4eXRs0DCw-V_2jR9igtFs_mOFMQufdL6tD-38,1323
10
10
  pykubegrader/graders/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
11
11
  pykubegrader/graders/late_assignments.py,sha256=_2-rA5RqO0BWY9WAQA_mbCxxPKTOiJOl-byD2CYWaE0,1393
12
12
  pykubegrader/log_parser/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
13
- pykubegrader/log_parser/parse.ipynb,sha256=GnEgUmowdN2bZSwwWgxqi43QXaP-syPD2SnHvOGq1vU,11674
13
+ pykubegrader/log_parser/parse.ipynb,sha256=H1CUuqiUSE-tiZV1IS7VG6HAEvoopGd6i_5QM5CwoE0,12230
14
14
  pykubegrader/log_parser/parse.py,sha256=YCs_OCnoxQKsL55MjTZWXBBBsehJL8PIB9ANnC-aE44,7379
15
15
  pykubegrader/widgets/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
16
16
  pykubegrader/widgets/multiple_choice.py,sha256=NjD3-uXSnibpUQ0mO3hRp_O-rynFyl0Dz6IXE4tnCRI,2078
@@ -24,9 +24,9 @@ pykubegrader/widgets_base/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-
24
24
  pykubegrader/widgets_base/multi_select.py,sha256=Cl0IN21wXLZuFu-zC65aS9tD4jMfzCRJ2DPjHao5_Ak,4044
25
25
  pykubegrader/widgets_base/reading.py,sha256=_vjUPynqmJe_R4vf-7hVhGnQR726S9GL6qT8bflBXBM,5383
26
26
  pykubegrader/widgets_base/select.py,sha256=Fw3uFNOIWo1a3CvlzSx23bvi6bSmA3TqutuRbhD4Dp8,2525
27
- PyKubeGrader-0.2.5.dist-info/LICENSE.txt,sha256=YTp-Ewc8Kems8PJEE27KnBPFnZSxoWvSg7nnknzPyYw,1546
28
- PyKubeGrader-0.2.5.dist-info/METADATA,sha256=0L7k_-gCWttmW6AyUgyOGon0znpg7WpiXTEm4TWgrxY,2729
29
- PyKubeGrader-0.2.5.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
30
- PyKubeGrader-0.2.5.dist-info/entry_points.txt,sha256=UPMdTT46fQwTYJWtrUwIWIbXbwyOPfNQgBFRa0frWzw,138
31
- PyKubeGrader-0.2.5.dist-info/top_level.txt,sha256=e550Klfze6higFxER1V62fnGOcIgiKRbsrl9CC4UdtQ,13
32
- PyKubeGrader-0.2.5.dist-info/RECORD,,
27
+ PyKubeGrader-0.2.6.dist-info/LICENSE.txt,sha256=YTp-Ewc8Kems8PJEE27KnBPFnZSxoWvSg7nnknzPyYw,1546
28
+ PyKubeGrader-0.2.6.dist-info/METADATA,sha256=_XXXPzB7wxkhmlAFJDZwa5s2BCzFQ3-kzU4tncrn2IA,2729
29
+ PyKubeGrader-0.2.6.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
30
+ PyKubeGrader-0.2.6.dist-info/entry_points.txt,sha256=UPMdTT46fQwTYJWtrUwIWIbXbwyOPfNQgBFRa0frWzw,138
31
+ PyKubeGrader-0.2.6.dist-info/top_level.txt,sha256=e550Klfze6higFxER1V62fnGOcIgiKRbsrl9CC4UdtQ,13
32
+ PyKubeGrader-0.2.6.dist-info/RECORD,,
@@ -1,3 +1,7 @@
1
+ ### Note
2
+
3
+
4
+
1
5
  import argparse
2
6
  import importlib.util
3
7
  import json
@@ -22,7 +26,7 @@ except: # noqa: E722
22
26
  import nbformat
23
27
 
24
28
  from .api_notebook_builder import FastAPINotebookBuilder
25
-
29
+ from typing import Optional
26
30
 
27
31
  @dataclass
28
32
  class NotebookProcessor:
@@ -66,6 +70,7 @@ class NotebookProcessor:
66
70
  self.assignment_type = self.assignment_tag.split("-")[0].lower()
67
71
  week_num = self.assignment_tag.split("-")[-1]
68
72
 
73
+ self.week_num = week_num
69
74
  self.week = f"week_{week_num}"
70
75
 
71
76
  # Define the folder to store solutions and ensure it exists
@@ -155,7 +160,22 @@ class NotebookProcessor:
155
160
 
156
161
  if self.check_if_file_in_folder("assignment_config.yaml"):
157
162
  self.add_assignment()
158
-
163
+
164
+ self.update_initialize_function()
165
+
166
+ def update_initialize_function(self):
167
+
168
+ for key, value in self.total_point_log.items():
169
+
170
+ assignment_tag = f"week{self.week_num}-{self.assignment_type}"
171
+
172
+ update_initialize_assignment(
173
+ notebook_path = os.path.join(self.root_folder, key + '.ipynb'),
174
+ assignment_points= value,
175
+ assignment_tag = assignment_tag,
176
+ )
177
+
178
+
159
179
  def build_payload(self, yaml_content):
160
180
  """
161
181
  Reads YAML content for an assignment and returns Python variables.
@@ -1380,7 +1400,6 @@ def extract_MCQ(ipynb_file):
1380
1400
  print("Invalid JSON in notebook file.")
1381
1401
  return []
1382
1402
 
1383
-
1384
1403
  def check_for_heading(notebook_path, search_strings):
1385
1404
  """
1386
1405
  Checks if a Jupyter notebook contains a heading cell whose source matches any of the given strings.
@@ -1826,6 +1845,69 @@ def replace_cell_source(notebook_path, cell_index, new_source):
1826
1845
  # Save the notebook
1827
1846
  with open(notebook_path, "w", encoding="utf-8") as f:
1828
1847
  nbformat.write(notebook, f)
1848
+
1849
+ def update_initialize_assignment(
1850
+ notebook_path: str,
1851
+ assignment_points: Optional[float] = None,
1852
+ assignment_tag: Optional[str] = None,
1853
+ ) -> None:
1854
+ """
1855
+ Search for a specific line in a Jupyter Notebook and update it with additional input variables.
1856
+
1857
+ Args:
1858
+ notebook_path (str): The path to the Jupyter Notebook file (.ipynb).
1859
+ assignment_points (Optional[float]): The assignment points variable to add (default is None).
1860
+ assignment_tag (Optional[str]): The assignment tag variable to add (default is None).
1861
+
1862
+ Returns:
1863
+ None
1864
+ """
1865
+ # Load the notebook content
1866
+ with open(notebook_path, "r", encoding="utf-8") as file:
1867
+ notebook_data = json.load(file)
1868
+
1869
+ # Pattern to match the specific initialize_assignment line
1870
+ pattern = re.compile(r"responses\s*=\s*initialize_assignment\((.*?)\)")
1871
+
1872
+ # Collect additional variables
1873
+ additional_variables = []
1874
+ if assignment_points is not None:
1875
+ additional_variables.append(f"assignment_points = {assignment_points}")
1876
+ if assignment_tag is not None:
1877
+ additional_variables.append(f"assignment_tag = '{assignment_tag}'")
1878
+
1879
+ # Join additional variables into a string
1880
+ additional_variables_str = ", ".join(additional_variables)
1881
+
1882
+ # Flag to check if any replacements were made
1883
+ updated = False
1884
+
1885
+ # Iterate through notebook cells
1886
+ for cell in notebook_data.get("cells", []):
1887
+ if cell.get("cell_type") == "code": # Only modify code cells
1888
+ source_code = cell.get("source", [])
1889
+ for i, line in enumerate(source_code):
1890
+ match = pattern.search(line)
1891
+ if match:
1892
+ # Extract existing arguments
1893
+ existing_args = match.group(1).strip()
1894
+ # Replace with the updated line
1895
+ if additional_variables_str:
1896
+ updated_line = (
1897
+ f"responses = initialize_assignment({existing_args}, {additional_variables_str})\n"
1898
+ )
1899
+ else:
1900
+ updated_line = f"responses = initialize_assignment({existing_args})\n"
1901
+ source_code[i] = updated_line
1902
+ updated = True
1903
+
1904
+ # If updated, save the notebook
1905
+ if updated:
1906
+ with open(notebook_path, "w", encoding="utf-8") as file:
1907
+ json.dump(notebook_data, file, indent=2)
1908
+ print(f"Notebook '{notebook_path}' has been updated.")
1909
+ else:
1910
+ print(f"No matching lines found in '{notebook_path}'.")
1829
1911
 
1830
1912
 
1831
1913
  def main():
@@ -6,16 +6,18 @@ from pathlib import Path
6
6
  import panel as pn
7
7
  import requests
8
8
  from IPython import get_ipython
9
-
9
+ from typing import Optional
10
10
  from .telemetry import ensure_responses, log_variable, telemetry, update_responses
11
11
 
12
12
 
13
13
  def initialize_assignment(
14
14
  name: str,
15
- week: int,
15
+ week: str,
16
16
  assignment_type: str,
17
17
  url: str = "https://engr-131-api.eastus.cloudapp.azure.com/",
18
18
  verbose: bool = False,
19
+ assignment_points: Optional[float] = None,
20
+ assignment_tag: Optional[str] = None,
19
21
  ) -> dict:
20
22
  """
21
23
  Initialize an assignment in a Jupyter environment.
@@ -75,6 +77,8 @@ def initialize_assignment(
75
77
  except Exception as e:
76
78
  raise Exception(f"Failed to initialize assignment: {e}")
77
79
 
80
+ log_variable("total-points", f"{assignment_tag}, {name}", assignment_points)
81
+
78
82
  print("Assignment successfully initialized")
79
83
  if verbose:
80
84
  print(f"Assignment: {name}")
@@ -1,5 +1,22 @@
1
1
  {
2
2
  "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "# Get the public/private keypair for decryption\n",
10
+ "key_box = get_keybox()"
11
+ ]
12
+ },
13
+ {
14
+ "cell_type": "code",
15
+ "execution_count": null,
16
+ "metadata": {},
17
+ "outputs": [],
18
+ "source": []
19
+ },
3
20
  {
4
21
  "cell_type": "code",
5
22
  "execution_count": null,
@@ -134,7 +151,7 @@
134
151
  "parser = LogParser(log_lines=log_lines, week_tag=\"week1-readings\")\n",
135
152
  "parser.parse_logs()\n",
136
153
  "parser.calculate_total_scores()\n",
137
- "results = parser.get_results()\n",
154
+ "results = parser.get_results() \n",
138
155
  "\n",
139
156
  "results"
140
157
  ]
@@ -182,6 +199,15 @@
182
199
  "outputs": [],
183
200
  "source": []
184
201
  },
202
+ {
203
+ "cell_type": "code",
204
+ "execution_count": null,
205
+ "metadata": {},
206
+ "outputs": [],
207
+ "source": [
208
+ "type(results[\"student_information\"][\"timestamp\"])"
209
+ ]
210
+ },
185
211
  {
186
212
  "cell_type": "code",
187
213
  "execution_count": null,
@@ -190,16 +216,23 @@
190
216
  "source": [
191
217
  "student_email = results[\"student_information\"][\"username\"]\n",
192
218
  "time_stamp = results[\"student_information\"][\"timestamp\"]\n",
193
- "assignments_graded = results[\"assignment_information\"].keys()\n",
219
+ "\n",
194
220
  "week_num = results[\"week_num\"]\n",
195
221
  "assignment_type = results['assignment_type']\n",
196
222
  "\n",
197
- "\n",
223
+ "assignments_graded = results[\"assignment_information\"].keys()\n",
198
224
  "total_score = 0\n",
199
225
  "for assignment in assignments_graded:\n",
200
- " max_points = results[\"assignment_information\"][assignment][\"max_points\"]\n",
201
- " total_score = results[\"assignment_information\"][assignment][\"total_score\"]\n",
202
- "\n"
226
+ " total_score += results[\"assignment_information\"][assignment][\"total_score\"]"
227
+ ]
228
+ },
229
+ {
230
+ "cell_type": "code",
231
+ "execution_count": null,
232
+ "metadata": {},
233
+ "outputs": [],
234
+ "source": [
235
+ "total_score"
203
236
  ]
204
237
  },
205
238
  {
@@ -217,7 +250,9 @@
217
250
  "execution_count": null,
218
251
  "metadata": {},
219
252
  "outputs": [],
220
- "source": []
253
+ "source": [
254
+ "student_email"
255
+ ]
221
256
  },
222
257
  {
223
258
  "cell_type": "code",