ygrader 2.6.12__tar.gz → 2.6.14__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.
Files changed (24) hide show
  1. {ygrader-2.6.12/ygrader.egg-info → ygrader-2.6.14}/PKG-INFO +1 -1
  2. {ygrader-2.6.12 → ygrader-2.6.14}/setup.py +1 -1
  3. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/grader.py +20 -5
  4. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/utils.py +46 -0
  5. {ygrader-2.6.12 → ygrader-2.6.14/ygrader.egg-info}/PKG-INFO +1 -1
  6. {ygrader-2.6.12 → ygrader-2.6.14}/LICENSE +0 -0
  7. {ygrader-2.6.12 → ygrader-2.6.14}/setup.cfg +0 -0
  8. {ygrader-2.6.12 → ygrader-2.6.14}/test/test_interactive.py +0 -0
  9. {ygrader-2.6.12 → ygrader-2.6.14}/test/test_unittest.py +0 -0
  10. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/__init__.py +0 -0
  11. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/deductions.py +0 -0
  12. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/feedback.py +0 -0
  13. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/grades_csv.py +0 -0
  14. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/grading_item.py +0 -0
  15. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/grading_item_config.py +0 -0
  16. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/remote.py +0 -0
  17. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/score_input.py +0 -0
  18. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/send_ctrl_backtick.ahk +0 -0
  19. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/student_repos.py +0 -0
  20. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader/upstream_merger.py +0 -0
  21. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader.egg-info/SOURCES.txt +0 -0
  22. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader.egg-info/dependency_links.txt +0 -0
  23. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader.egg-info/requires.txt +0 -0
  24. {ygrader-2.6.12 → ygrader-2.6.14}/ygrader.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ygrader
3
- Version: 2.6.12
3
+ Version: 2.6.14
4
4
  Summary: Grading scripts used in BYU's Electrical and Computer Engineering Department
5
5
  Home-page: https://github.com/byu-cpe/ygrader
6
6
  Author: Jeff Goeders
@@ -4,7 +4,7 @@ setup(
4
4
  name="ygrader",
5
5
  packages=["ygrader"],
6
6
  package_data={"ygrader": ["*.ahk"]},
7
- version="2.6.12",
7
+ version="2.6.14",
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",
@@ -537,8 +537,8 @@ class Grader:
537
537
  continue
538
538
 
539
539
  # Print name(s) of who we are grading
540
- student_work_path = self.work_path / utils.names_to_dir(
541
- first_names, last_names, net_ids
540
+ student_work_path = self._get_student_work_path(
541
+ row, first_names, last_names, net_ids
542
542
  )
543
543
  print_color(
544
544
  TermColors.PURPLE,
@@ -567,7 +567,9 @@ class Grader:
567
567
  callback_args["first_names"] = first_names
568
568
  callback_args["last_names"] = last_names
569
569
  callback_args["net_ids"] = net_ids
570
- callback_args["output"] = sys.stdout # Default to stdout in sequential mode
570
+ callback_args["output"] = (
571
+ sys.stdout
572
+ ) # Default to stdout in sequential mode
571
573
  if self.code_source == CodeSource.GITHUB:
572
574
  callback_args["repo_url"] = row["github_url"]
573
575
  callback_args["tag"] = self.github_tag
@@ -663,8 +665,8 @@ class Grader:
663
665
  )
664
666
  log_path = log_file.name
665
667
 
666
- student_work_path = self.work_path / utils.names_to_dir(
667
- first_names, last_names, net_ids
668
+ student_work_path = self._get_student_work_path(
669
+ row, first_names, last_names, net_ids
668
670
  )
669
671
 
670
672
  # Build student info dict to pass to helper
@@ -868,6 +870,19 @@ class Grader:
868
870
  df["submitted_zip_path"] = df["submitted_zip_path"].fillna(value="")
869
871
  return df
870
872
 
873
+ def _get_student_work_path(self, row, first_names, last_names, net_ids):
874
+ """Get the work path for a student/group.
875
+
876
+ For GitHub submissions, the folder is named after the repository name.
877
+ For Learning Suite submissions, it uses the first student's name.
878
+ """
879
+ if self.code_source == CodeSource.GITHUB:
880
+ # Use the repository name from the GitHub URL
881
+ repo_name = utils.github_url_to_repo_name(row["github_url"])
882
+ return self.work_path / repo_name
883
+ # Learning Suite: use first student's name
884
+ return self.work_path / utils.names_to_dir(first_names, last_names, net_ids)
885
+
871
886
  def _group_students(self, df):
872
887
  if self.code_source == CodeSource.GITHUB:
873
888
  # For Github source, group name is simply github URL
@@ -8,6 +8,7 @@ import subprocess
8
8
  import hashlib
9
9
  import time
10
10
  import os
11
+ import shlex
11
12
 
12
13
 
13
14
  class TermColors:
@@ -85,6 +86,31 @@ def names_to_dir(first_names, last_names, net_ids):
85
86
  )
86
87
 
87
88
 
89
+ def github_url_to_repo_name(url):
90
+ """Extract the repository name from a GitHub URL.
91
+
92
+ Works with both SSH and HTTPS formats:
93
+ >>> github_url_to_repo_name("git@github.com:byu-ecen123-classroom/123-labs-team01.git")
94
+ '123-labs-team01'
95
+ >>> github_url_to_repo_name("https://github.com/byu-ecen123-classroom/123-labs-team01")
96
+ '123-labs-team01'
97
+ >>> github_url_to_repo_name("https://github.com/byu-ecen123-classroom/123-labs-team01.git")
98
+ '123-labs-team01'
99
+ """
100
+ # Try SSH format: git@github.com:org/repo.git
101
+ match = re.search(r"git@github\.com:.*?/(.*?)(?:\.git)?$", url)
102
+ if match:
103
+ return match.group(1)
104
+
105
+ # Try HTTPS format: https://github.com/org/repo or https://github.com/org/repo.git
106
+ match = re.search(r"github\.com/.*?/(.*?)(?:\.git)?$", url)
107
+ if match:
108
+ return match.group(1)
109
+
110
+ # Fallback: return the URL as-is (shouldn't happen with valid GitHub URLs)
111
+ return url
112
+
113
+
88
114
  def hash_file(file_path):
89
115
  """Returns a hash of a file"""
90
116
 
@@ -163,6 +189,26 @@ def is_wsl():
163
189
  _FOCUS_WARNING_PRINTED = False
164
190
 
165
191
 
192
+ def opener(file_path, sleep_time=1.0):
193
+ """Open a file using VS Code or a custom opener defined in the OPENER environment variable.
194
+
195
+ Parameters
196
+ ----------
197
+ file_path: pathlib.Path or str
198
+ Path to the file to open
199
+ sleep_time: float, optional
200
+ Time in seconds to wait for the editor to open (default: 1.0)
201
+ """
202
+ if "OPENER" not in os.environ:
203
+ open_file_in_vscode(file_path, sleep_time)
204
+ else:
205
+ subprocess.run(
206
+ f'{os.environ["OPENER"]} {shlex.quote(str(file_path))}',
207
+ shell=True,
208
+ check=False,
209
+ )
210
+
211
+
166
212
  def open_file_in_vscode(file_path, sleep_time=1.0):
167
213
  """Open a file in VS Code and return focus to terminal.
168
214
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ygrader
3
- Version: 2.6.12
3
+ Version: 2.6.14
4
4
  Summary: Grading scripts used in BYU's Electrical and Computer Engineering Department
5
5
  Home-page: https://github.com/byu-cpe/ygrader
6
6
  Author: Jeff Goeders
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes