ygrader 2.6.7__tar.gz → 2.6.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ygrader-2.6.7/ygrader.egg-info → ygrader-2.6.11}/PKG-INFO +1 -1
- {ygrader-2.6.7 → ygrader-2.6.11}/setup.py +1 -1
- {ygrader-2.6.7 → ygrader-2.6.11}/test/test_unittest.py +3 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/grader.py +15 -13
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/grading_item.py +0 -1
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/score_input.py +5 -5
- {ygrader-2.6.7 → ygrader-2.6.11/ygrader.egg-info}/PKG-INFO +1 -1
- {ygrader-2.6.7 → ygrader-2.6.11}/LICENSE +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/setup.cfg +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/test/test_interactive.py +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/__init__.py +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/deductions.py +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/feedback.py +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/grades_csv.py +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/grading_item_config.py +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/remote.py +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/send_ctrl_backtick.ahk +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/student_repos.py +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/upstream_merger.py +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader/utils.py +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader.egg-info/SOURCES.txt +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader.egg-info/dependency_links.txt +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader.egg-info/requires.txt +0 -0
- {ygrader-2.6.7 → ygrader-2.6.11}/ygrader.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ setup(
|
|
|
4
4
|
name="ygrader",
|
|
5
5
|
packages=["ygrader"],
|
|
6
6
|
package_data={"ygrader": ["*.ahk"]},
|
|
7
|
-
version="2.6.
|
|
7
|
+
version="2.6.11",
|
|
8
8
|
description="Grading scripts used in BYU's Electrical and Computer Engineering Department",
|
|
9
9
|
author="Jeff Goeders",
|
|
10
10
|
author_email="jeff.goeders@gmail.com",
|
|
@@ -50,6 +50,7 @@ class TestGithub(unittest.TestCase):
|
|
|
50
50
|
grader.set_submission_system_github(
|
|
51
51
|
"main", TEST_RESOURCES_PATH / "github.csv", use_https=True
|
|
52
52
|
)
|
|
53
|
+
grader.set_other_options(show_completion_menu=False)
|
|
53
54
|
grader.run()
|
|
54
55
|
|
|
55
56
|
self.assertTrue(filecmp.cmp(deductions1_yaml_path, deductions1_golden_path))
|
|
@@ -83,6 +84,7 @@ class TestLearningSuite(unittest.TestCase):
|
|
|
83
84
|
grader.set_submission_system_learning_suite(
|
|
84
85
|
TEST_RESOURCES_PATH / "submissions.zip"
|
|
85
86
|
)
|
|
87
|
+
grader.set_other_options(show_completion_menu=False)
|
|
86
88
|
grader.run()
|
|
87
89
|
|
|
88
90
|
self.assertTrue(filecmp.cmp(deductions_path, deductions_golden_path))
|
|
@@ -127,6 +129,7 @@ class TestLearningSuite(unittest.TestCase):
|
|
|
127
129
|
TEST_RESOURCES_PATH / "submissions2.zip"
|
|
128
130
|
)
|
|
129
131
|
grader.set_learning_suite_groups(TEST_RESOURCES_PATH / "groups3.csv")
|
|
132
|
+
grader.set_other_options(show_completion_menu=False)
|
|
130
133
|
grader.run()
|
|
131
134
|
|
|
132
135
|
self.assertTrue(filecmp.cmp(deductions1_path, deductions1_golden_path))
|
|
@@ -21,7 +21,7 @@ import pandas
|
|
|
21
21
|
|
|
22
22
|
from . import grades_csv, student_repos, utils
|
|
23
23
|
from .grading_item import GradeItem
|
|
24
|
-
from .score_input import
|
|
24
|
+
from .score_input import display_completion_menu
|
|
25
25
|
from .utils import (
|
|
26
26
|
CallbackFailed,
|
|
27
27
|
TermColors,
|
|
@@ -100,7 +100,7 @@ class Grader:
|
|
|
100
100
|
self.code_source = None
|
|
101
101
|
self.prep_fcn = None
|
|
102
102
|
self.last_graded_net_ids = None # Track last fully graded student for undo
|
|
103
|
-
self.
|
|
103
|
+
self.show_completion_menu = True # Show menu when grading completes
|
|
104
104
|
self.learning_suite_submissions_zip_path = None
|
|
105
105
|
self.github_csv_path = None
|
|
106
106
|
self.github_csv_col_name = None
|
|
@@ -345,6 +345,7 @@ class Grader:
|
|
|
345
345
|
dry_run_all=False,
|
|
346
346
|
workflow_hash=None,
|
|
347
347
|
parallel_workers=None,
|
|
348
|
+
show_completion_menu=True,
|
|
348
349
|
):
|
|
349
350
|
"""
|
|
350
351
|
This can be used to set other options for the grader.
|
|
@@ -390,6 +391,9 @@ class Grader:
|
|
|
390
391
|
If set to an integer, process students in parallel using that many workers.
|
|
391
392
|
Only works with build_only mode since interactive grading cannot be parallelized.
|
|
392
393
|
Default is None (sequential processing).
|
|
394
|
+
show_completion_menu: bool
|
|
395
|
+
Whether to show the completion menu when all students are graded.
|
|
396
|
+
Default is True.
|
|
393
397
|
"""
|
|
394
398
|
self.format_code = format_code
|
|
395
399
|
self.build_only = build_only
|
|
@@ -419,6 +423,8 @@ class Grader:
|
|
|
419
423
|
if parallel_workers is not None and not build_only:
|
|
420
424
|
error("parallel_workers is only supported when build_only=True")
|
|
421
425
|
|
|
426
|
+
self.show_completion_menu = show_completion_menu
|
|
427
|
+
|
|
422
428
|
def _validate_config(self):
|
|
423
429
|
"""Check that everything has been configured before running"""
|
|
424
430
|
# Check that callback function has been set up
|
|
@@ -498,17 +504,16 @@ class Grader:
|
|
|
498
504
|
self._run_grading_sequential(student_grades_df, grouped_df)
|
|
499
505
|
|
|
500
506
|
def _run_grading_sequential(self, student_grades_df, grouped_df):
|
|
501
|
-
# Sort by
|
|
502
|
-
# After groupby().agg(list), "
|
|
507
|
+
# Sort by first name for consistent grading order (matches display name sorting in [g] menu)
|
|
508
|
+
# After groupby().agg(list), "First Name" is a list, so we sort by the first element
|
|
503
509
|
sorted_df = grouped_df.sort_values(
|
|
504
|
-
by="
|
|
510
|
+
by="First Name", key=lambda x: x.apply(lambda names: names[0].lower())
|
|
505
511
|
)
|
|
506
512
|
|
|
507
513
|
# Convert to list for index-based iteration (needed for going back)
|
|
508
514
|
rows_list = list(sorted_df.iterrows())
|
|
509
515
|
idx = 0
|
|
510
516
|
prev_idx = None # Track previous student index for undo
|
|
511
|
-
any_student_needed_grading = False # Track if any student needed grading
|
|
512
517
|
|
|
513
518
|
# Loop through all of the students/groups and perform grading
|
|
514
519
|
while idx < len(rows_list):
|
|
@@ -528,8 +533,6 @@ class Grader:
|
|
|
528
533
|
idx += 1
|
|
529
534
|
continue
|
|
530
535
|
|
|
531
|
-
any_student_needed_grading = True
|
|
532
|
-
|
|
533
536
|
# Print name(s) of who we are grading
|
|
534
537
|
student_work_path = self.work_path / utils.names_to_dir(
|
|
535
538
|
first_names, last_names, net_ids
|
|
@@ -617,17 +620,16 @@ class Grader:
|
|
|
617
620
|
prev_idx = idx
|
|
618
621
|
idx += 1
|
|
619
622
|
|
|
620
|
-
# Show completion menu when all students are done (unless in special modes)
|
|
621
|
-
# Show if interactive grading occurred OR if no students needed grading (all already graded)
|
|
623
|
+
# Show completion menu when all students are done (unless disabled or in special modes)
|
|
622
624
|
if (
|
|
623
|
-
|
|
625
|
+
self.show_completion_menu
|
|
626
|
+
and not self.build_only
|
|
624
627
|
and not self.dry_run_first
|
|
625
628
|
and not self.dry_run_all
|
|
626
|
-
and (self.interactive_grading_occurred or not any_student_needed_grading)
|
|
627
629
|
):
|
|
628
630
|
# Get names_by_netid from first item for display purposes
|
|
629
631
|
names_by_netid = self.items[0].names_by_netid if self.items else None
|
|
630
|
-
|
|
632
|
+
display_completion_menu(self.items, names_by_netid)
|
|
631
633
|
|
|
632
634
|
def _process_single_student_build(self, row):
|
|
633
635
|
"""Process a single student for parallel build mode. Returns (net_ids, success, message, log_path)."""
|
|
@@ -40,7 +40,7 @@ def _print_menu_item(cmd, description, indent=" ", pad=10):
|
|
|
40
40
|
)
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
def
|
|
43
|
+
def display_completion_menu(items, names_by_netid=None):
|
|
44
44
|
"""Show a menu when all students have been graded.
|
|
45
45
|
|
|
46
46
|
Allows the user to manage grades, edit deduction types, etc.
|
|
@@ -191,8 +191,8 @@ def get_score(
|
|
|
191
191
|
)
|
|
192
192
|
print(fpad2 + "Current deductions:")
|
|
193
193
|
if current_deductions:
|
|
194
|
-
for
|
|
195
|
-
print(fpad2 + f" -{
|
|
194
|
+
for deduction in current_deductions:
|
|
195
|
+
print(fpad2 + f" -{deduction.points}: {deduction.message}")
|
|
196
196
|
else:
|
|
197
197
|
print(fpad2 + " (None)")
|
|
198
198
|
print("")
|
|
@@ -328,8 +328,8 @@ def get_score(
|
|
|
328
328
|
# Fallback for single item - wrap in list
|
|
329
329
|
# Create a minimal item-like object for backwards compatibility
|
|
330
330
|
class _SingleItemWrapper:
|
|
331
|
-
def __init__(self,
|
|
332
|
-
self.student_deductions =
|
|
331
|
+
def __init__(self, student_deductions_arg):
|
|
332
|
+
self.student_deductions = student_deductions_arg
|
|
333
333
|
|
|
334
334
|
_manage_grades_interactive(
|
|
335
335
|
[_SingleItemWrapper(student_deductions)], names_by_netid
|
|
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
|