PyKubeGrader 0.2.10__tar.gz → 0.2.11__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {pykubegrader-0.2.10/src/PyKubeGrader.egg-info → pykubegrader-0.2.11}/PKG-INFO +1 -1
- {pykubegrader-0.2.10 → pykubegrader-0.2.11/src/PyKubeGrader.egg-info}/PKG-INFO +1 -1
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/build/build_folder.py +66 -1
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/submit/submit_assignment.py +9 -5
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/.coveragerc +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/.github/workflows/main.yml +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/.gitignore +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/.readthedocs.yml +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/AUTHORS.rst +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/CHANGELOG.rst +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/CONTRIBUTING.rst +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/LICENSE.txt +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/README.rst +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/Makefile +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/_static/Drexel_blue_Logo_square_Dark.png +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/_static/Drexel_blue_Logo_square_Light.png +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/_static/custom.css +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/authors.rst +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/changelog.rst +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/conf.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/contributing.rst +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/index.rst +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/license.rst +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/readme.rst +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/docs/requirements.txt +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/examples/.responses.json +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/examples/true_false.ipynb +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/pyproject.toml +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/setup.cfg +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/setup.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/PyKubeGrader.egg-info/SOURCES.txt +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/PyKubeGrader.egg-info/dependency_links.txt +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/PyKubeGrader.egg-info/entry_points.txt +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/PyKubeGrader.egg-info/not-zip-safe +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/PyKubeGrader.egg-info/requires.txt +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/PyKubeGrader.egg-info/top_level.txt +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/__init__.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/build/__init__.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/build/api_notebook_builder.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/build/clean_folder.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/graders/__init__.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/graders/late_assignments.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/initialize.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/log_parser/__init__.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/log_parser/parse.ipynb +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/log_parser/parse.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/telemetry.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/utils.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/validate.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets/__init__.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets/multiple_choice.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets/reading_question.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets/select_many.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets/student_info.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets/style.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets/true_false.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets/types_question.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets_base/__init__.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets_base/multi_select.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets_base/reading.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/src/pykubegrader/widgets_base/select.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/tests/conftest.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/tests/import_test.py +0 -0
- {pykubegrader-0.2.10 → pykubegrader-0.2.11}/tox.ini +0 -0
@@ -215,6 +215,68 @@ class NotebookProcessor:
|
|
215
215
|
"due_date": due_date,
|
216
216
|
"max_score": int(self.assignment_total_points),
|
217
217
|
}
|
218
|
+
|
219
|
+
def build_payload_notebook(self, yaml_content, notebook_title, total_points):
|
220
|
+
# Parse the YAML content
|
221
|
+
with open(yaml_content, "r") as file:
|
222
|
+
data = yaml.safe_load(file)
|
223
|
+
|
224
|
+
# Extract assignment details
|
225
|
+
assignment = data.get("assignment", {})
|
226
|
+
|
227
|
+
week_num = self.week_num
|
228
|
+
assignment_type = self.assignment_type
|
229
|
+
due_date_str = assignment.get("due_date")
|
230
|
+
|
231
|
+
# Convert due_date to a datetime object if available
|
232
|
+
due_date = None
|
233
|
+
if due_date_str:
|
234
|
+
try:
|
235
|
+
due_date = parser.parse(due_date_str) # Automatically handles timezones
|
236
|
+
except ValueError as e:
|
237
|
+
print(f"Error parsing due_date: {e}")
|
238
|
+
|
239
|
+
return {
|
240
|
+
"title": notebook_title,
|
241
|
+
"week_number": week_num,
|
242
|
+
"assignment_type": assignment_type,
|
243
|
+
"due_date": due_date,
|
244
|
+
"max_score": total_points,
|
245
|
+
}
|
246
|
+
|
247
|
+
|
248
|
+
def add_notebook(self, notebook_title, total_points):
|
249
|
+
"""
|
250
|
+
Sends a POST request to add a notebook.
|
251
|
+
"""
|
252
|
+
# Define the URL
|
253
|
+
url = "https://engr-131-api.eastus.cloudapp.azure.com/notebook"
|
254
|
+
|
255
|
+
# Build the payload
|
256
|
+
payload = self.build_payload_notebook(yaml_content=f"{self.root_folder}/assignment_config.yaml",
|
257
|
+
notebook_title=notebook_title,
|
258
|
+
total_points=total_points)
|
259
|
+
|
260
|
+
# Define HTTP Basic Authentication
|
261
|
+
auth = (user(), password())
|
262
|
+
|
263
|
+
# Define headers
|
264
|
+
headers = {"Content-Type": "application/json"}
|
265
|
+
|
266
|
+
# Serialize the payload with the custom JSON encoder
|
267
|
+
serialized_payload = json.dumps(payload, default=self.json_serial)
|
268
|
+
|
269
|
+
# Send the POST request
|
270
|
+
response = requests.post(
|
271
|
+
url, data=serialized_payload, headers=headers, auth=auth
|
272
|
+
)
|
273
|
+
|
274
|
+
# Print the response
|
275
|
+
print(f"Status Code: {response.status_code}")
|
276
|
+
try:
|
277
|
+
print(f"Response: {response.json()}")
|
278
|
+
except ValueError:
|
279
|
+
print(f"Response: {response.text}")
|
218
280
|
|
219
281
|
def add_assignment(self):
|
220
282
|
"""
|
@@ -436,6 +498,9 @@ class NotebookProcessor:
|
|
436
498
|
+ self.tf_total_points
|
437
499
|
+ self.otter_total_points
|
438
500
|
)
|
501
|
+
|
502
|
+
# creates the assignment record in the database
|
503
|
+
self.add_notebook(notebook_name, total_points)
|
439
504
|
|
440
505
|
self.assignment_total_points += total_points
|
441
506
|
|
@@ -466,7 +531,7 @@ class NotebookProcessor:
|
|
466
531
|
# Define the Code cell
|
467
532
|
code_cell = nbformat.v4.new_code_cell(
|
468
533
|
"from pykubegrader.submit.submit_assignment import submit_assignment\n\n"
|
469
|
-
f'submit_assignment("week{self.week_num}-{self.assignment_type}")'
|
534
|
+
f'submit_assignment("week{self.week_num}-{self.assignment_type}", "{os.path.basename(notebook_path).replace(".ipynb", "")}")'
|
470
535
|
)
|
471
536
|
|
472
537
|
# Make the code cell non-editable and non-deletable
|
@@ -22,7 +22,7 @@ def get_credentials():
|
|
22
22
|
|
23
23
|
|
24
24
|
async def call_score_assignment(
|
25
|
-
assignment_title: str, file_path: str = ".output_reduced.log"
|
25
|
+
assignment_title: str, notebook_title: str, file_path: str = ".output_reduced.log"
|
26
26
|
) -> dict:
|
27
27
|
"""
|
28
28
|
Submit an assignment to the scoring endpoint.
|
@@ -38,7 +38,7 @@ async def call_score_assignment(
|
|
38
38
|
base_url = os.getenv("DB_URL")
|
39
39
|
if not base_url:
|
40
40
|
raise ValueError("Environment variable 'DB_URL' is not set.")
|
41
|
-
url = f"{base_url}score-assignment?assignment_title={assignment_title}"
|
41
|
+
url = f"{base_url}score-assignment?assignment_title={assignment_title}¬ebook_title={notebook_title}"
|
42
42
|
|
43
43
|
# Get credentials
|
44
44
|
credentials = get_credentials()
|
@@ -46,7 +46,9 @@ async def call_score_assignment(
|
|
46
46
|
password = credentials["password"]
|
47
47
|
|
48
48
|
# Encode credentials for Basic Authentication
|
49
|
-
auth_header =
|
49
|
+
auth_header = (
|
50
|
+
f"Basic {base64.b64encode(f'{username}:{password}'.encode()).decode()}"
|
51
|
+
)
|
50
52
|
|
51
53
|
# Send the POST request
|
52
54
|
async with httpx.AsyncClient() as client:
|
@@ -71,7 +73,9 @@ async def call_score_assignment(
|
|
71
73
|
|
72
74
|
|
73
75
|
def submit_assignment(
|
74
|
-
assignment_title: str,
|
76
|
+
assignment_title: str,
|
77
|
+
notebook_title: str,
|
78
|
+
file_path: str = ".output_reduced.log",
|
75
79
|
) -> None:
|
76
80
|
"""
|
77
81
|
Synchronous wrapper for the `call_score_assignment` function.
|
@@ -89,7 +93,7 @@ def submit_assignment(
|
|
89
93
|
|
90
94
|
# Run the async function in the event loop
|
91
95
|
response = loop.run_until_complete(
|
92
|
-
call_score_assignment(assignment_title, file_path)
|
96
|
+
call_score_assignment(assignment_title, notebook_title, file_path)
|
93
97
|
)
|
94
98
|
print("Server Response:", response.get("message", "No message in response"))
|
95
99
|
|
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
|