-
Notifications
You must be signed in to change notification settings - Fork 25
Implement include_remote_repo option #246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0ffb340
0ea4b5e
18529bb
2d78fbc
5fbe3a3
ef12c68
2bdf5c2
0202a23
73de85d
f894599
5b8dd12
7f8674e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,7 +3,19 @@ | |||||||||
| from contextlib import contextmanager | ||||||||||
| from datetime import datetime | ||||||||||
| from pathlib import Path | ||||||||||
| from typing import Callable, ContextManager, Dict, Iterator, List, Optional, Self, Tuple | ||||||||||
| from typing import ( | ||||||||||
| Any, | ||||||||||
| Callable, | ||||||||||
| ContextManager, | ||||||||||
| Dict, | ||||||||||
| Iterator, | ||||||||||
| List, | ||||||||||
| Literal, | ||||||||||
| Optional, | ||||||||||
| Self, | ||||||||||
| Tuple, | ||||||||||
| overload, | ||||||||||
| ) | ||||||||||
| from unittest import mock | ||||||||||
|
|
||||||||||
| import pytz | ||||||||||
|
|
@@ -45,21 +57,30 @@ def __init__( | |||||||||
| grade_func: Callable[[GitAutograderExercise], GitAutograderOutput], | ||||||||||
| clone_from: Optional[str] = None, | ||||||||||
| mock_answers: Optional[Dict[str, str]] = None, | ||||||||||
| include_remote_repo: bool = False, | ||||||||||
| ) -> None: | ||||||||||
| self.exercise_name = exercise_name | ||||||||||
| self.grade_func = grade_func | ||||||||||
| self.clone_from = clone_from | ||||||||||
| self.mock_answers = mock_answers | ||||||||||
| self.include_remote_repo = include_remote_repo | ||||||||||
| self.__rs: Optional[RepoSmith] = None | ||||||||||
| self.__rs_remote: Optional[RepoSmith] = None | ||||||||||
| self.__rs_context: Optional[ContextManager[RepoSmith]] = None | ||||||||||
| self.__rs_remote_context: Optional[ContextManager[RepoSmith]] = None | ||||||||||
| self.__temp_dir: Optional[tempfile.TemporaryDirectory] = None | ||||||||||
| self.__remote_temp_dir: Optional[tempfile.TemporaryDirectory] = None | ||||||||||
| self.__patches: List[mock._patch] = [] | ||||||||||
|
|
||||||||||
| @property | ||||||||||
| def rs(self) -> RepoSmith: | ||||||||||
| assert self.__rs is not None | ||||||||||
| return self.__rs | ||||||||||
|
|
||||||||||
| @property | ||||||||||
| def rs_remote(self) -> Optional[RepoSmith]: | ||||||||||
| return self.__rs_remote | ||||||||||
|
|
||||||||||
| def run(self) -> GitAutograderOutput: | ||||||||||
| output: Optional[GitAutograderOutput] = None | ||||||||||
| started_at = datetime.now(tz=pytz.UTC) | ||||||||||
|
|
@@ -95,7 +116,7 @@ def run(self) -> GitAutograderOutput: | |||||||||
| assert output is not None | ||||||||||
| return output | ||||||||||
|
|
||||||||||
| def __enter__(self) -> Tuple[Self, RepoSmith]: | ||||||||||
| def __enter__(self) -> Tuple[Self, RepoSmith, RepoSmith | None]: | ||||||||||
| # We will mock all accesses to the config to avoid reading the file itself | ||||||||||
| # Only the exercise name and repo_name matters, everything else isn't used | ||||||||||
| repo_name = "repo" | ||||||||||
|
|
@@ -165,7 +186,18 @@ def __enter__(self) -> Tuple[Self, RepoSmith]: | |||||||||
| self.__rs = self.__rs_context.__enter__() | ||||||||||
| self.__rs.add_helper(GitMasteryHelper) | ||||||||||
|
|
||||||||||
| return self, self.rs | ||||||||||
| if self.include_remote_repo: | ||||||||||
| self.__remote_temp_dir = tempfile.TemporaryDirectory() | ||||||||||
| remote_temp_path = Path(self.__remote_temp_dir.name) | ||||||||||
| remote_repo_path = remote_temp_path / repo_name | ||||||||||
| os.makedirs(remote_repo_path, exist_ok=True) | ||||||||||
| self.__rs_remote_context = create_repo_smith( | ||||||||||
| False, existing_path=remote_repo_path.absolute().as_posix() | ||||||||||
| ) | ||||||||||
| self.__rs_remote = self.__rs_remote_context.__enter__() | ||||||||||
| self.__rs_remote.add_helper(GitMasteryHelper) | ||||||||||
|
|
||||||||||
| return self, self.rs, self.rs_remote | ||||||||||
|
||||||||||
| return self, self.rs, self.rs_remote | |
| if self.include_remote_repo: | |
| return self, self.rs, self.rs_remote | |
| return self, self.rs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes type arguments complicated and results in failure in mypy test cases, so we only extract out the relevant variables at start() based on include_remote_repo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally, I would avoid using Any as type, but it seems to make the most sense here.
I tried returning Tuple[GitAutograderTest, RepoSmith, RepoSmith] | Tuple[GitAutograderTest, RepoSmith] but it seems that Python's type system can't narrow a union return type based on instance attributes at call time.
Having the @overload here seems to be the best solution for type safety.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, without @overload, users lose the precision of return type when include_remote_repo is set to True/False.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a small remark, for consistency,
existing_path...should be on a new line.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code be auto-formatted by ruff