PyKubeGrader 0.2.8__py3-none-any.whl → 0.2.10__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.8
3
+ Version: 0.2.10
4
4
  Summary: Add a short description here!
5
5
  Home-page: https://github.com/pyscaffold/pyscaffold/
6
6
  Author: jagar2
@@ -5,14 +5,14 @@ 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=g8yRRGmHxW_47WHpFPsH9tiuFgFrvcxBPJwjZyFMS_w,74895
8
+ pykubegrader/build/build_folder.py,sha256=hNHfhCn2rAHUK_i-KbtZYhUbd_bYsAoPRm2vVK9gYi8,76508
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
13
  pykubegrader/log_parser/parse.ipynb,sha256=H1CUuqiUSE-tiZV1IS7VG6HAEvoopGd6i_5QM5CwoE0,12230
14
14
  pykubegrader/log_parser/parse.py,sha256=YCs_OCnoxQKsL55MjTZWXBBBsehJL8PIB9ANnC-aE44,7379
15
- pykubegrader/submit/submit_assignment.py,sha256=UHRwogSz7TpMUZSAyEbQIQut2WcC08ma2JEIEWaSUdM,2702
15
+ pykubegrader/submit/submit_assignment.py,sha256=f8mQ96d0EpI5FNhdauGj21ybSZEzBEYsuG25a-Jel-c,3289
16
16
  pykubegrader/widgets/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
17
17
  pykubegrader/widgets/multiple_choice.py,sha256=NjD3-uXSnibpUQ0mO3hRp_O-rynFyl0Dz6IXE4tnCRI,2078
18
18
  pykubegrader/widgets/reading_question.py,sha256=y30_swHwzH8LrT8deWTnxctAAmR8BSxTlXAqMgUrAT4,3031
@@ -25,9 +25,9 @@ pykubegrader/widgets_base/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-
25
25
  pykubegrader/widgets_base/multi_select.py,sha256=Cl0IN21wXLZuFu-zC65aS9tD4jMfzCRJ2DPjHao5_Ak,4044
26
26
  pykubegrader/widgets_base/reading.py,sha256=_vjUPynqmJe_R4vf-7hVhGnQR726S9GL6qT8bflBXBM,5383
27
27
  pykubegrader/widgets_base/select.py,sha256=Fw3uFNOIWo1a3CvlzSx23bvi6bSmA3TqutuRbhD4Dp8,2525
28
- PyKubeGrader-0.2.8.dist-info/LICENSE.txt,sha256=YTp-Ewc8Kems8PJEE27KnBPFnZSxoWvSg7nnknzPyYw,1546
29
- PyKubeGrader-0.2.8.dist-info/METADATA,sha256=KDlsQ-0emWgalUlulH1-hifPtv1M7kzHulEJlcLDmtM,2778
30
- PyKubeGrader-0.2.8.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
31
- PyKubeGrader-0.2.8.dist-info/entry_points.txt,sha256=UPMdTT46fQwTYJWtrUwIWIbXbwyOPfNQgBFRa0frWzw,138
32
- PyKubeGrader-0.2.8.dist-info/top_level.txt,sha256=e550Klfze6higFxER1V62fnGOcIgiKRbsrl9CC4UdtQ,13
33
- PyKubeGrader-0.2.8.dist-info/RECORD,,
28
+ PyKubeGrader-0.2.10.dist-info/LICENSE.txt,sha256=YTp-Ewc8Kems8PJEE27KnBPFnZSxoWvSg7nnknzPyYw,1546
29
+ PyKubeGrader-0.2.10.dist-info/METADATA,sha256=VlXNrYslMa8YjmEQWQ67wCuII-K0uGZXKHeEDcAkSro,2779
30
+ PyKubeGrader-0.2.10.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
31
+ PyKubeGrader-0.2.10.dist-info/entry_points.txt,sha256=UPMdTT46fQwTYJWtrUwIWIbXbwyOPfNQgBFRa0frWzw,138
32
+ PyKubeGrader-0.2.10.dist-info/top_level.txt,sha256=e550Klfze6higFxER1V62fnGOcIgiKRbsrl9CC4UdtQ,13
33
+ PyKubeGrader-0.2.10.dist-info/RECORD,,
@@ -434,12 +434,55 @@ class NotebookProcessor:
434
434
  self.select_many_total_points
435
435
  + self.mcq_total_points
436
436
  + self.tf_total_points
437
- + self.otter_total_points
437
+ + self.otter_total_points
438
438
  )
439
439
 
440
440
  self.assignment_total_points += total_points
441
441
 
442
442
  self.total_point_log.update({notebook_name: total_points})
443
+
444
+ student_file_path = os.path.join(self.root_folder, notebook_name + '.ipynb')
445
+ self.add_submission_cells(student_file_path, student_file_path)
446
+
447
+ def add_submission_cells(self, notebook_path: str, output_path: str) -> None:
448
+ """
449
+ Adds submission cells to the end of a Jupyter notebook.
450
+
451
+ Args:
452
+ notebook_path (str): Path to the input notebook.
453
+ output_path (str): Path to save the modified notebook.
454
+ """
455
+ # Load the notebook
456
+ with open(notebook_path, "r", encoding="utf-8") as f:
457
+ notebook = nbformat.read(f, as_version=4)
458
+
459
+ # Define the Markdown cell
460
+ markdown_cell = nbformat.v4.new_markdown_cell(
461
+ "## Submitting Assignment\n\n"
462
+ "Please run the following block of code using `shift + enter` to submit your assignment, "
463
+ "you should see your score."
464
+ )
465
+
466
+ # Define the Code cell
467
+ code_cell = nbformat.v4.new_code_cell(
468
+ "from pykubegrader.submit.submit_assignment import submit_assignment\n\n"
469
+ f'submit_assignment("week{self.week_num}-{self.assignment_type}")'
470
+ )
471
+
472
+ # Make the code cell non-editable and non-deletable
473
+ code_cell.metadata = {
474
+ "editable": False,
475
+ "deletable": False
476
+ }
477
+
478
+ # Add the cells to the notebook
479
+ notebook.cells.append(markdown_cell)
480
+ notebook.cells.append(code_cell)
481
+
482
+ # Save the modified notebook
483
+ with open(output_path, "w", encoding="utf-8") as f:
484
+ nbformat.write(notebook, f)
485
+
443
486
 
444
487
  def free_response_parser(
445
488
  self, temp_notebook_path, notebook_subfolder, notebook_name
@@ -1,9 +1,10 @@
1
1
  import os
2
2
  import httpx
3
3
  import asyncio
4
-
5
4
  import nest_asyncio
5
+ import base64
6
6
 
7
+ # Apply nest_asyncio for environments like Jupyter
7
8
  nest_asyncio.apply()
8
9
 
9
10
 
@@ -37,10 +38,15 @@ async def call_score_assignment(
37
38
  base_url = os.getenv("DB_URL")
38
39
  if not base_url:
39
40
  raise ValueError("Environment variable 'DB_URL' is not set.")
40
- url = f"{base_url}score-assignment"
41
+ url = f"{base_url}score-assignment?assignment_title={assignment_title}"
41
42
 
42
43
  # Get credentials
43
44
  credentials = get_credentials()
45
+ username = credentials["username"]
46
+ password = credentials["password"]
47
+
48
+ # Encode credentials for Basic Authentication
49
+ auth_header = f"Basic {base64.b64encode(f'{username}:{password}'.encode()).decode()}"
44
50
 
45
51
  # Send the POST request
46
52
  async with httpx.AsyncClient() as client:
@@ -48,8 +54,8 @@ async def call_score_assignment(
48
54
  with open(file_path, "rb") as file:
49
55
  response = await client.post(
50
56
  url,
51
- data={"cred": credentials, "assignment_title": assignment_title},
52
- files={"log_file": file},
57
+ headers={"Authorization": auth_header}, # Add Authorization header
58
+ files={"log_file": file}, # Upload log file
53
59
  )
54
60
 
55
61
  # Handle the response
@@ -64,7 +70,6 @@ async def call_score_assignment(
64
70
  raise RuntimeError(f"An unexpected error occurred: {e}")
65
71
 
66
72
 
67
- # Importable function
68
73
  def submit_assignment(
69
74
  assignment_title: str, file_path: str = ".output_reduced.log"
70
75
  ) -> None:
@@ -75,10 +80,20 @@ def submit_assignment(
75
80
  assignment_title (str): Title of the assignment.
76
81
  file_path (str): Path to the log file to upload.
77
82
  """
78
- response = asyncio.run(call_score_assignment(assignment_title, file_path))
83
+ # Get the current event loop or create one
84
+ try:
85
+ loop = asyncio.get_event_loop()
86
+ except RuntimeError:
87
+ loop = asyncio.new_event_loop()
88
+ asyncio.set_event_loop(loop)
89
+
90
+ # Run the async function in the event loop
91
+ response = loop.run_until_complete(
92
+ call_score_assignment(assignment_title, file_path)
93
+ )
79
94
  print("Server Response:", response.get("message", "No message in response"))
80
95
 
81
96
 
82
97
  # Example usage (remove this section if only the function needs to be importable):
83
98
  if __name__ == "__main__":
84
- submit_assignment("Week 1 Assignment", "path/to/your/log_file.txt")
99
+ submit_assignment("week1-readings", "path/to/your/log_file.txt")