PyKubeGrader 0.2.4__tar.gz → 0.2.6__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. {pykubegrader-0.2.4/src/PyKubeGrader.egg-info → pykubegrader-0.2.6}/PKG-INFO +1 -1
  2. {pykubegrader-0.2.4 → pykubegrader-0.2.6/src/PyKubeGrader.egg-info}/PKG-INFO +1 -1
  3. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/build/build_folder.py +85 -3
  4. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/initialize.py +6 -2
  5. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/log_parser/parse.ipynb +42 -7
  6. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/telemetry.py +3 -1
  7. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/.coveragerc +0 -0
  8. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/.github/workflows/main.yml +0 -0
  9. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/.gitignore +0 -0
  10. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/.readthedocs.yml +0 -0
  11. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/AUTHORS.rst +0 -0
  12. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/CHANGELOG.rst +0 -0
  13. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/CONTRIBUTING.rst +0 -0
  14. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/LICENSE.txt +0 -0
  15. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/README.rst +0 -0
  16. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/Makefile +0 -0
  17. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/_static/Drexel_blue_Logo_square_Dark.png +0 -0
  18. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/_static/Drexel_blue_Logo_square_Light.png +0 -0
  19. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/_static/custom.css +0 -0
  20. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/authors.rst +0 -0
  21. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/changelog.rst +0 -0
  22. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/conf.py +0 -0
  23. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/contributing.rst +0 -0
  24. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/index.rst +0 -0
  25. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/license.rst +0 -0
  26. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/readme.rst +0 -0
  27. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/docs/requirements.txt +0 -0
  28. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/examples/.responses.json +0 -0
  29. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/examples/true_false.ipynb +0 -0
  30. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/pyproject.toml +0 -0
  31. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/setup.cfg +0 -0
  32. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/setup.py +0 -0
  33. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/PyKubeGrader.egg-info/SOURCES.txt +0 -0
  34. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/PyKubeGrader.egg-info/dependency_links.txt +0 -0
  35. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/PyKubeGrader.egg-info/entry_points.txt +0 -0
  36. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/PyKubeGrader.egg-info/not-zip-safe +0 -0
  37. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/PyKubeGrader.egg-info/requires.txt +0 -0
  38. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/PyKubeGrader.egg-info/top_level.txt +0 -0
  39. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/__init__.py +0 -0
  40. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/build/__init__.py +0 -0
  41. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/build/api_notebook_builder.py +0 -0
  42. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/build/clean_folder.py +0 -0
  43. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/graders/__init__.py +0 -0
  44. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/graders/late_assignments.py +0 -0
  45. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/log_parser/__init__.py +0 -0
  46. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/log_parser/parse.py +0 -0
  47. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/utils.py +0 -0
  48. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/validate.py +0 -0
  49. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets/__init__.py +0 -0
  50. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets/multiple_choice.py +0 -0
  51. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets/reading_question.py +0 -0
  52. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets/select_many.py +0 -0
  53. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets/student_info.py +0 -0
  54. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets/style.py +0 -0
  55. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets/true_false.py +0 -0
  56. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets/types_question.py +0 -0
  57. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets_base/__init__.py +0 -0
  58. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets_base/multi_select.py +0 -0
  59. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets_base/reading.py +0 -0
  60. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/src/pykubegrader/widgets_base/select.py +0 -0
  61. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/tests/conftest.py +0 -0
  62. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/tests/import_test.py +0 -0
  63. {pykubegrader-0.2.4 → pykubegrader-0.2.6}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyKubeGrader
3
- Version: 0.2.4
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PyKubeGrader
3
- Version: 0.2.4
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,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",
@@ -85,7 +85,9 @@ def log_encrypted(logger: logging.Logger, message: str) -> None:
85
85
 
86
86
 
87
87
  def log_variable(assignment_name, value, info_type) -> None:
88
- timestamp = datetime.datetime.now(datetime.UTC).strftime("%Y-%m-%d %H:%M:%S")
88
+ timestamp = datetime.datetime.now(datetime.UTC).isoformat(
89
+ sep=" ", timespec="seconds"
90
+ )
89
91
  message = f"{assignment_name}, {info_type}, {value}, {timestamp}"
90
92
  log_encrypted(logger_reduced, message)
91
93
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes