change create_symlink with type hints and error handling - #257
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors the create_symlink function in src/mainutils.py to use pathlib for more robust path handling and adds logic to manage existing destination files or directories. The review feedback identifies a missing pathlib import that would lead to a NameError and highlights that resolving the source path to an absolute path may break relative symlinks, suggesting the use of the original source path to ensure portability.
f1ba182 to
abd19fc
Compare
|
gemini-code-assist was good this time. |
4fddefd to
69a4b58
Compare
|
Yes, it was effective on this one.
The only thing I'm a little bit against is the nested conditionals and
excessive on that front.
Do we need so many? Could we use AND/OR logic?
…On 30.04.2026 04:38, Marvin1099 wrote:
marvin1099 left a comment (DeckCheatz/wemod-launcher#257)
[gemini-code-assist](https://github.com/apps/gemini-code-assist) was good this time.
Fixed missing `import pathlib`
and using a resolved path only for checks not for making the link to maintain relative paths.
Force pushed to keep commits clean.
--
Reply to this email directly or view it on GitHub:
#257 (comment)
You are receiving this because your review was requested.
Message ID: ***@***.***>
|
69a4b58 to
1a48847
Compare
Flattend code as to your request. |
65f0d31 to
67b691c
Compare
|
Thanks.
Looks like you need to rebase again, and then we can do a onceover of
this PR. Might be worth triggering Gemini again.
…On 01.05.2026 01:00, Marvin1099 wrote:
marvin1099 left a comment (DeckCheatz/wemod-launcher#257)
> Yes, it was effective on this one. The only thing I'm a little bit against is the nested conditionals and excessive on that front. Do we need so many? Could we use AND/OR logic?
Flattend code as to your request.
--
Reply to this email directly or view it on GitHub:
#257 (comment)
You are receiving this because your review was requested.
Message ID: ***@***.***>
|
f92143b to
36f1884
Compare
|
Now its rebased |
|
/gemini review |
|
Just prodding Gemini for another review, and then I'll test. |
There was a problem hiding this comment.
Code Review
This pull request refactors src/mainutils.py by moving pathlib imports to the top level and rewriting the create_symlink function with type hints and enhanced replacement logic. However, the refactored function introduces critical bugs: it incorrectly resolves relative paths relative to the current working directory instead of the destination's parent, contains a logic error that prevents creating new symlinks when replace is False, and risks crashing by calling unlink on non-existent paths.
|
@marvin1099 I'm not sure what you think of the bot's recent review, but I'd like to make sure the launcher doesn't crash. OOI, what version of Python are you on? I'm on 3.13.x, but if people use varying levels of Python (before we transition to a compiled binary), it could have unexpected behaviour between systems. |
36f1884 to
9e3dedc
Compare
|
Fixed. I know what a long comment. |
a0b5690 to
65f0d31
Compare
9e3dedc to
f825cb6
Compare
|
@marvin1099 I've rebased this PR, would like to get it into my PR soon 👍 |
|
/gemini review |
Refactor create_symlink function to add type hints and enhance error handling for existing symlinks and files.
f825cb6 to
a507fe2
Compare
65f0d31 to
6c9d41d
Compare
There was a problem hiding this comment.
Code Review
This pull request removes the requests dependency by implementing a custom http_get utility and a SimpleResponse class based on urllib.request. It also refactors create_symlink to use pathlib for more robust path management. Feedback highlights issues in SimpleResponse where the text property consumes the entire stream and iter_content is not reusable. Additionally, the default destructive behavior of create_symlink when encountering directories was flagged as a safety concern.
I am having trouble creating individual review comments. Click here to see my feedback.
src/coreutils.py (91-95)
The text property has a side effect of consuming the entire response stream when _stream is True. This exhausts the underlying socket, which means any subsequent attempts to use iter_content() will return no data. Additionally, it loads the entire content into memory, defeating the purpose of streaming for large files. It is recommended to avoid consuming the stream in a property getter or to cache the content in a way that doesn't break the streaming interface.
src/coreutils.py (108-111)
The iter_content method uses an instance variable self._content_pos to track iteration progress for non-streamed content. This makes the response object's content iterable only once. Subsequent calls to iter_content() will yield nothing because self._content_pos remains at the end of the content. It is better to use a local variable for the iteration to allow multiple passes over the cached data.
else:
for i in range(0, len(self.content), chunk_size):
yield self.content[i:i + chunk_size]src/mainutils.py (721-724)
The create_symlink function defaults to replace=True, which triggers shutil.rmtree(dst_path) if the destination is a directory. This is a highly destructive operation for a utility function that users might expect to only manage symlinks or files. A safer approach would be to default replace to None or False, or to require an explicit confirmation/flag before recursively deleting a directory tree to prevent accidental data loss.
|
That was a old push, I've fixed it now. I'll re-run the review with Gemini. |
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request refactors src/mainutils.py by promoting the pathlib import to the top level and rewriting the create_symlink function to include type hints and more robust path resolution. Review feedback suggests simplifying the path resolution logic and type hints. Additionally, a high-severity safety concern was raised regarding the default replace=True parameter, which could lead to unintended recursive directory deletion via shutil.rmtree.
| os.remove(dst) | ||
| os.symlink(src, dst) | ||
|
|
||
| def create_symlink(src: Union[str, pathlib.Path], dst: Union[str, pathlib.Path], replace: Union[bool, None] = True) -> None: |
There was a problem hiding this comment.
The type hint Union[bool, None] can be simplified to Optional[bool] since Optional is already imported. More importantly, defaulting replace to True is dangerous because it allows shutil.rmtree to recursively delete entire directory trees by default if they exist at the destination. This is a significant departure from the previous implementation's safety. It is highly recommended to change the default to None (replace only files and symlinks) or False for safety.
| def create_symlink(src: Union[str, pathlib.Path], dst: Union[str, pathlib.Path], replace: Union[bool, None] = True) -> None: | |
| def create_symlink(src: Union[str, pathlib.Path], dst: Union[str, pathlib.Path], replace: Optional[bool] = None) -> None: |
|
|
||
| # Resolve source relative to destination parent | ||
| # because relative symlink targets are interpreted there | ||
| check_src = (dst_path.parent / src_path).resolve() if not src_path.is_absolute() else src_path.resolve() |
There was a problem hiding this comment.
The conditional check if not src_path.is_absolute() is redundant when using pathlib. Joining a path with an absolute path (e.g., parent / absolute_src) automatically returns the absolute path. This can be simplified to a single expression.
| check_src = (dst_path.parent / src_path).resolve() if not src_path.is_absolute() else src_path.resolve() | |
| check_src = (dst_path.parent / src_path).resolve() |
Refactor create_symlink function to add type hints and enhance error handling for existing symlinks and files.
This is how i would change create_symlink.