-
Notifications
You must be signed in to change notification settings - Fork 26
Improve rclone transfer output detail. #623
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
f49735b to
f6434b6
Compare
e02bc41 to
bc27a76
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
This PR enhances rclone transfer output logging by parsing JSON-formatted logs to extract and display error details and transfer statistics. The implementation adds error tracking throughout the transfer pipeline, from the core rclone wrapper to the TUI and API, enabling users to see specific file errors and warnings when no files are transferred.
Key Changes:
- Added
TransferErrorsTypedDict to track file-level errors and transfer completion status - Implemented JSON log parsing in
rclone.pyto extract errors and statistics from rclone output - Modified all transfer functions to return error information for display in both API and TUI contexts
Reviewed Changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| datashuttle/utils/custom_types.py | Added TransferErrors TypedDict to define the structure for error tracking |
| datashuttle/utils/rclone.py | Implemented JSON log parsing, error extraction, and formatting functions for rclone output |
| datashuttle/utils/data_transfer.py | Modified TransferData class to return errors from transfer operations |
| datashuttle/datashuttle_class.py | Updated all transfer methods to return TransferErrors and display error summaries |
| datashuttle/tui/interface.py | Updated TUI interface transfer methods to pass errors to UI components |
| datashuttle/tui/screens/modal_dialogs.py | Enhanced MessageBox to support variable sizing and display detailed error messages |
| datashuttle/tui/css/tui_menu.tcss | Moved messagebox sizing from CSS to Python for dynamic adjustment |
| datashuttle/utils/ssh.py | Fixed missing newline character in error message |
| pyproject.toml | Added filelock dependency for testing file locking scenarios |
| tests/test_utils.py | Added lock_a_file utility function for simulating file locks in tests |
| tests/tests_tui/test_tui_transfer.py | Added comprehensive test for error display in TUI pop-ups |
| tests/tests_transfers/local_filesystem/test_transfer.py | Added test to verify errors variable is properly returned from all transfer functions |
| tests/tests_integration/test_logging.py | Added test to verify errors are caught, logged, and displayed correctly |
| tests/tests_tui/tui_base.py | Added optional parameter to control messagebox closing in transfer helper |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| test_utils.delete_log_files(project.cfg.logging_path) | ||
|
|
||
| test_utils.delete_log_files(project.cfg.logging_path) |
Copilot
AI
Nov 20, 2025
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.
Duplicate call to delete_log_files. This line is redundant as the same call is made on line 518.
| test_utils.delete_log_files(project.cfg.logging_path) |
| """""" | ||
|
|
Copilot
AI
Nov 20, 2025
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.
Missing docstring. This function should have a docstring that describes its purpose, parameters, and return value.
| """""" | |
| """ | |
| Lock a file by writing to it continuously for a specified duration in a separate thread. | |
| Parameters | |
| ---------- | |
| file_path : str or Path | |
| The path to the file to be locked. | |
| duration : int, optional | |
| The duration in seconds to keep the file locked (default is 5). | |
| Returns | |
| ------- | |
| threading.Thread | |
| The thread object that is writing to the file. | |
| """ |
| utils.log_and_message(message) | ||
|
|
||
|
|
||
| def log_rclone_copy_errors_api(errors): |
Copilot
AI
Nov 20, 2025
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.
Missing type hints. The function should include type hints for the errors parameter (should be TransferErrors) to improve type safety and code clarity.
| def log_rclone_copy_errors_api(errors): | |
| def log_rclone_copy_errors_api(errors: "TransferErrors"): |
| utils.log_and_message(message, use_rich=True) | ||
|
|
||
|
|
||
| def parse_rclone_copy_output(top_level_folder, output): |
Copilot
AI
Nov 20, 2025
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.
Missing type hints. The function should include type hints for the top_level_folder parameter (should be TopLevelFolder | None) and the output parameter (should be CompletedProcess) for better type safety.
| def parse_rclone_copy_output(top_level_folder, output): | |
| def parse_rclone_copy_output( | |
| top_level_folder: TopLevelFolder | None, output: CompletedProcess | |
| ) -> tuple[str, str, dict]: |
|
|
||
| self.check_input_arguments() | ||
|
|
||
| def run(self): |
Copilot
AI
Nov 20, 2025
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.
Missing return type hint. The run method should have a return type hint of TransferErrors. This would require importing TransferErrors from datashuttle.utils.custom_types.
| "nothing_was_transferred_rawdata": err_errors[ | ||
| "nothing_was_transferred_rawdata" | ||
| ], | ||
| "nothing_was_transferred_derivatives": err_errors[ | ||
| "nothing_was_transferred_derivatives" | ||
| ], |
Copilot
AI
Nov 20, 2025
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.
Potential data loss when combining errors. When combining errors from stdout and stderr, only the nothing_was_transferred flags from err_errors are used. If out_errors also contains relevant information (e.g., nothing_was_transferred_rawdata or nothing_was_transferred_derivatives is set), it will be lost. Consider merging these flags with appropriate logic (e.g., using OR logic or choosing the non-None value).
| "nothing_was_transferred_rawdata": err_errors[ | |
| "nothing_was_transferred_rawdata" | |
| ], | |
| "nothing_was_transferred_derivatives": err_errors[ | |
| "nothing_was_transferred_derivatives" | |
| ], | |
| "nothing_was_transferred_rawdata": ( | |
| out_errors["nothing_was_transferred_rawdata"] | |
| if out_errors["nothing_was_transferred_rawdata"] is not None | |
| else err_errors["nothing_was_transferred_rawdata"] | |
| ), | |
| "nothing_was_transferred_derivatives": ( | |
| out_errors["nothing_was_transferred_derivatives"] | |
| if out_errors["nothing_was_transferred_derivatives"] is not None | |
| else err_errors["nothing_was_transferred_derivatives"] | |
| ), |
| if any(errors["messages"]): | ||
| if errors["file_names"]: | ||
| errors_message += ( | ||
| "\n[red]Errors detected! in files:[/red]\n" |
Copilot
AI
Nov 20, 2025
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.
Inconsistent capitalization in error message. The error message "Errors detected! in files:" has inconsistent capitalization - "in" should be capitalized as "In" to match the sentence structure, or the exclamation mark should be replaced with a comma.
| "\n[red]Errors detected! in files:[/red]\n" | |
| "\n[red]Errors detected, in files:[/red]\n" |
|
|
||
| # Transfer again to check the message displays indicating | ||
| # no files were transferred. | ||
| await self.run_transfer(pilot, "upload") |
Copilot
AI
Nov 20, 2025
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.
Redundant transfer operation. The transfer is run twice consecutively (lines 295 and 297-299). The first call on line 295 closes the messagebox immediately, which seems unnecessary since the second call on line 297 is the one being tested. Consider removing line 295.
| await self.run_transfer(pilot, "upload") |
| height | ||
| The height of the messagebox. | ||
| width | ||
| The width of the messagebox. | ||
Copilot
AI
Nov 20, 2025
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.
Inconsistent parameter order in docstring. The docstring lists parameters in the order message, border_color, height, width, but the function signature has them in the order message, border_color, width, height. The docstring should match the function signature order.
| height | |
| The height of the messagebox. | |
| width | |
| The width of the messagebox. | |
| width | |
| The width of the messagebox. | |
| height | |
| The height of the messagebox. |
| else: | ||
| self.app.show_modal_error_dialog(output) | ||
|
|
||
| except BaseException as e: |
Copilot
AI
Nov 20, 2025
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.
Except block directly handles BaseException.
| except BaseException as e: | |
| except Exception as e: |
This PR improves the detail on the rclone copy log output and highlights all errors in the transfer message.
In the python API, a short summary is printed after the logs. In the TUI, a 'warning' is given if nothing as transferred:
and errors are show:
These are generatede from directly parsing the rclone logs. I am waiting for somone from RClone to check this approach here, I will follow up on / improve the request if Id ont hear back soon.