PyKubeGrader 0.2.8__tar.gz → 0.2.10__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {pykubegrader-0.2.8/src/PyKubeGrader.egg-info → pykubegrader-0.2.10}/PKG-INFO +1 -1
- {pykubegrader-0.2.8 → pykubegrader-0.2.10/src/PyKubeGrader.egg-info}/PKG-INFO +1 -1
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/build/build_folder.py +44 -1
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/submit/submit_assignment.py +22 -7
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/.coveragerc +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/.github/workflows/main.yml +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/.gitignore +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/.readthedocs.yml +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/AUTHORS.rst +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/CHANGELOG.rst +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/CONTRIBUTING.rst +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/LICENSE.txt +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/README.rst +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/Makefile +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/_static/Drexel_blue_Logo_square_Dark.png +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/_static/Drexel_blue_Logo_square_Light.png +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/_static/custom.css +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/authors.rst +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/changelog.rst +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/conf.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/contributing.rst +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/index.rst +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/license.rst +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/readme.rst +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/docs/requirements.txt +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/examples/.responses.json +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/examples/true_false.ipynb +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/pyproject.toml +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/setup.cfg +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/setup.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/PyKubeGrader.egg-info/SOURCES.txt +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/PyKubeGrader.egg-info/dependency_links.txt +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/PyKubeGrader.egg-info/entry_points.txt +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/PyKubeGrader.egg-info/not-zip-safe +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/PyKubeGrader.egg-info/requires.txt +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/PyKubeGrader.egg-info/top_level.txt +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/__init__.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/build/__init__.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/build/api_notebook_builder.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/build/clean_folder.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/graders/__init__.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/graders/late_assignments.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/initialize.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/log_parser/__init__.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/log_parser/parse.ipynb +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/log_parser/parse.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/telemetry.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/utils.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/validate.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets/__init__.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets/multiple_choice.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets/reading_question.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets/select_many.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets/student_info.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets/style.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets/true_false.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets/types_question.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets_base/__init__.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets_base/multi_select.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets_base/reading.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/src/pykubegrader/widgets_base/select.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/tests/conftest.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/tests/import_test.py +0 -0
- {pykubegrader-0.2.8 → pykubegrader-0.2.10}/tox.ini +0 -0
@@ -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
|
-
|
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
|
-
|
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("
|
99
|
+
submit_assignment("week1-readings", "path/to/your/log_file.txt")
|
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
|
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
|
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
|
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
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|