-
Notifications
You must be signed in to change notification settings - Fork 35
Refactor and cleanup restartthinner #847
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
base: main
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #847 +/- ##
==========================================
+ Coverage 83.46% 83.56% +0.09%
==========================================
Files 49 49
Lines 7293 7294 +1
==========================================
+ Hits 6087 6095 +8
+ Misses 1206 1199 -7 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
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.
Pull request overview
This PR refactors and modernizes the restartthinner module by improving code quality, replacing deprecated patterns, and enhancing maintainability.
Changes:
- Replaced
os.system()calls withsubprocess.run()for better error handling and portability - Refactored
find_resdata_app()to useshutil.which()instead of manual PATH traversal - Simplified
date_slicer()to return a list directly instead of a dict, improving clarity
Comments suppressed due to low confidence (1)
src/subscript/restartthinner/restartthinner.py:69
- There are two spelling errors in this comment: "dont't" should be "don't" and "remainding" should be "remaining".
First unpacking a UNRST file, then deleting dates the dont't want, then
pack the remainding files into a new UNRST file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| String with path if found. | ||
| Raises: | ||
| IOError: if tool can't be found |
Copilot
AI
Jan 19, 2026
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 docstring states "IOError: if tool can't be found" but the function raises OSError. While IOError is an alias for OSError in Python 3, the docstring should be updated to match the actual exception being raised for consistency.
| IOError: if tool can't be found | |
| OSError: if tool can't be found |
| def date_slicer( | ||
| slicedates: list, restartdates: list, restartindices: list | ||
| ) -> list[int]: | ||
| """Make a dict that maps a chosen restart date to a report index""" |
Copilot
AI
Jan 19, 2026
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 docstring still mentions "Make a dict that maps a chosen restart date to a report index" but the function now returns a list instead of a dict. The docstring should be updated to reflect that it returns a list of restart indices.
| """Make a dict that maps a chosen restart date to a report index""" | |
| """Return a list of restart indices closest to the requested slice dates.""" |
56537b7 to
1b28dbe
Compare
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.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ) | ||
|
|
||
| # Move result back up | ||
| shutil.move(rstname, f"../{rstname}") |
Copilot
AI
Jan 19, 2026
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 path construction using string concatenation f"../{rstname}" is less robust and platform-agnostic than using Path operations. Consider using Path("..") / rstname instead for better portability and consistency with the rest of the codebase which uses Path objects.
| shutil.move(rstname, f"../{rstname}") | |
| shutil.move(rstname, Path("..") / rstname) |
| with _working_directory(rstdir): | ||
| tempdir = Path(tempfile.mkdtemp(dir=".")) | ||
| try: | ||
| # Move UNRST into temp directory and work there | ||
| shutil.move(rstname, tempdir / rstname) | ||
|
|
||
| with _working_directory(tempdir): | ||
| subprocess.run( | ||
| [rd_unpack, rstname], | ||
| capture_output=quiet, | ||
| check=True, | ||
| ) | ||
|
|
||
| for file in Path(".").glob("*.X*"): | ||
| index = int(file.suffix.lstrip(".X")) | ||
| if index not in slicerstindices: | ||
| file.unlink() | ||
|
|
||
| remaining_files = sorted(Path(".").glob("*.X*")) | ||
| subprocess.run( | ||
| [rd_pack, *[str(f) for f in remaining_files]], | ||
| capture_output=quiet, | ||
| check=True, | ||
| ) | ||
|
|
||
| # Move result back up | ||
| shutil.move(rstname, f"../{rstname}") | ||
| finally: | ||
| shutil.rmtree(tempdir) |
Copilot
AI
Jan 19, 2026
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.
If an error occurs in rd_repacker after moving the original file into the temp directory but before successfully moving it back, the original file could be lost when the temp directory is cleaned up in the finally block. This is especially problematic when keep=False. Consider creating a temporary backup inside rd_repacker or ensuring the original file is only moved after successful processing, using a different approach like working on a copy.
| subprocess.run( | ||
| [rd_unpack, rstname], | ||
| capture_output=quiet, | ||
| check=True, | ||
| ) | ||
|
|
||
| for file in Path(".").glob("*.X*"): | ||
| index = int(file.suffix.lstrip(".X")) | ||
| if index not in slicerstindices: | ||
| file.unlink() | ||
|
|
||
| remaining_files = sorted(Path(".").glob("*.X*")) | ||
| subprocess.run( | ||
| [rd_pack, *[str(f) for f in remaining_files]], | ||
| capture_output=quiet, | ||
| check=True, | ||
| ) |
Copilot
AI
Jan 19, 2026
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 subprocess.run calls use capture_output=quiet which will be either True or False. When True, both stdout and stderr are captured and discarded. When False, they are not captured. However, this means error messages from the subprocess will be hidden when quiet=True, making debugging difficult if the subprocess fails. Consider using stdout=subprocess.DEVNULL if quiet else None and always showing stderr for better error visibility, or at least including stderr in the exception message when check=True fails.
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.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
1b28dbe to
925b484
Compare
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.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
925b484 to
633967e
Compare
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.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if numberofslices > 1: | ||
| slicedates = pandas.DatetimeIndex( | ||
| numpy.linspace( | ||
| pandas.Timestamp(restart_dates[0]).value, | ||
| pandas.Timestamp(restart_dates[-1]).value, | ||
| slicedates = pd.DatetimeIndex( | ||
| np.linspace( | ||
| pd.Timestamp(restart_dates[0]).value, | ||
| pd.Timestamp(restart_dates[-1]).value, | ||
| int(numberofslices), | ||
| ) | ||
| ).to_list() | ||
| else: | ||
| slicedates = [restart_dates[-1]] # Only return last date if only one is wanted | ||
|
|
||
| slicerstindices = list( | ||
| date_slicer(slicedates, restart_dates, restart_indices).values() | ||
| ) | ||
| slicerstindices.sort() | ||
| slicerstindices = list(set(slicerstindices)) # uniquify | ||
| slicerstindices = date_slicer(slicedates, restart_dates, restart_indices) | ||
| slicerstindices = sorted(set(slicerstindices)) # uniquify |
Copilot
AI
Jan 19, 2026
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.
When numberofslices equals the number of existing restart points, the date_slicer logic may still try to calculate evenly-spaced dates which could theoretically select duplicates. The sorted(set(...)) on line 179 handles this, but it means the user might get fewer restart points than requested. Consider adding a check or warning when numberofslices >= len(restart_indices) to inform the user that all restart points are being kept.
| cwd = os.getcwd() | ||
| rstfilepath = Path(rstfilename).parent | ||
| tempdir = None | ||
| def rd_repacker(rstfilename: str, slicerstindices: list[int], quiet: bool) -> None: |
Copilot
AI
Jan 19, 2026
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 parameter name "slicerstindices" appears to have a typo - it should likely be "slicedrstindices" or "sliced_rst_indices" for clarity. The "r" seems to be missing between "slice" and "st", making it read as "slicer-st-indices" rather than "sliced-rst-indices" (sliced restart indices).
No description provided.