From df33152a3842d76fd4d93ff4bc9ab71fd4bc53a7 Mon Sep 17 00:00:00 2001 From: 2Shirt <2xShirt@gmail.com> Date: Mon, 13 May 2019 19:26:44 -0600 Subject: [PATCH] Pylint cleanup for ddrescue-tui part 1 --- .bin/Scripts/functions/ddrescue.py | 129 +++++++++++++++-------------- 1 file changed, 69 insertions(+), 60 deletions(-) diff --git a/.bin/Scripts/functions/ddrescue.py b/.bin/Scripts/functions/ddrescue.py index 545d08e0..3876b580 100644 --- a/.bin/Scripts/functions/ddrescue.py +++ b/.bin/Scripts/functions/ddrescue.py @@ -1,15 +1,14 @@ -# Wizard Kit: Functions - ddrescue-tui +# pylint: disable=no-name-in-module,too-many-lines,wildcard-import +# vim: sts=2 sw=2 ts=2 +'''Wizard Kit: Functions - ddrescue-tui''' import datetime import pathlib -import psutil -import pytz import re -import signal import stat import time +import pytz -from collections import OrderedDict from functions.data import * from functions.hw_diags import * from functions.json import * @@ -20,6 +19,7 @@ from settings.ddrescue import * # Clases class BaseObj(): + # pylint: disable=missing-docstring """Base object used by DevObj, DirObj, and ImageObj.""" def __init__(self, path): self.type = 'base' @@ -44,6 +44,7 @@ class BaseObj(): class BlockPair(): + # pylint: disable=too-many-instance-attributes """Object to track data and methods together for source and dest.""" def __init__(self, mode, source, dest): self.mode = mode @@ -153,6 +154,7 @@ class BlockPair(): class DevObj(BaseObj): + # pylint: disable=too-many-instance-attributes """Block device object.""" def self_check(self): """Verify that self.path points to a block device.""" @@ -186,6 +188,7 @@ class DevObj(BaseObj): self.update_filename_prefix() def update_filename_prefix(self): + # pylint: disable=attribute-defined-outside-init """Set filename prefix based on details.""" self.prefix = '{m_size}_{model}'.format( m_size=self.model_size, @@ -205,6 +208,7 @@ class DevObj(BaseObj): class DirObj(BaseObj): + """Directory object.""" def self_check(self): """Verify that self.path points to a directory.""" if not pathlib.Path(self.path).is_dir(): @@ -222,6 +226,7 @@ class DirObj(BaseObj): class ImageObj(BaseObj): + """Image file object.""" def self_check(self): """Verify that self.path points to a file.""" if not pathlib.Path(self.path).is_file(): @@ -247,6 +252,7 @@ class ImageObj(BaseObj): class RecoveryState(): + # pylint: disable=too-many-instance-attributes """Object to track BlockPair objects and overall state.""" def __init__(self, mode, source, dest): self.mode = mode.lower() @@ -317,15 +323,15 @@ class RecoveryState(): def current_pass_done(self): """Checks if pass is done for all block-pairs, returns bool.""" done = True - for bp in self.block_pairs: - done &= bp.pass_done[self.current_pass] + for b_p in self.block_pairs: + done &= b_p.pass_done[self.current_pass] return done def current_pass_min(self): """Gets minimum pass rescued percentage, returns float.""" min_percent = 100 - for bp in self.block_pairs: - min_percent = min(min_percent, bp.rescued_percent) + for b_p in self.block_pairs: + min_percent = min(min_percent, b_p.rescued_percent) return min_percent def get_smart_source(self): @@ -339,10 +345,10 @@ class RecoveryState(): def retry_all_passes(self): """Mark all passes as pending for all block-pairs.""" self.finished = False - for bp in self.block_pairs: - bp.pass_done = [False, False, False] - bp.status = ['Pending', 'Pending', 'Pending'] - bp.fix_status_strings() + for b_p in self.block_pairs: + b_p.pass_done = [False, False, False] + b_p.status = ['Pending', 'Pending', 'Pending'] + b_p.fix_status_strings() self.set_pass_num() def self_checks(self): @@ -361,7 +367,7 @@ class RecoveryState(): # Avoid saving map to non-persistent filesystem fstype = json_data.get( 'filesystems', [{}])[0].get( - 'fstype', 'unknown') + 'fstype', 'unknown') if fstype not in map_allowed_fstypes: print_error( "Map isn't being saved to a recommended filesystem ({})".format( @@ -374,10 +380,10 @@ class RecoveryState(): # Run BlockPair self checks and get total size self.total_size = 0 - for bp in self.block_pairs: - bp.self_check() - self.resumed |= bp.resumed - self.total_size += bp.size + for b_p in self.block_pairs: + b_p.self_check() + self.resumed |= b_p.resumed + self.total_size += b_p.size def set_pass_num(self): """Set current pass based on all block-pair's progress.""" @@ -385,8 +391,8 @@ class RecoveryState(): for pass_num in (2, 1, 0): # Iterate backwards through passes pass_done = True - for bp in self.block_pairs: - pass_done &= bp.pass_done[pass_num] + for b_p in self.block_pairs: + pass_done &= b_p.pass_done[pass_num] if pass_done: # All block-pairs reported being done # Set to next pass, unless we're on the last pass (2) @@ -413,7 +419,7 @@ class RecoveryState(): # Just set to N/A (NOTE: this overrules the refresh rate below) self.etoc = 'N/A' return - elif 'In Progress' not in self.status: + if 'In Progress' not in self.status: # Don't update when EToC is hidden return if now.second % ETOC_REFRESH_RATE != 0: @@ -427,7 +433,7 @@ class RecoveryState(): # Capture main tmux pane try: text = tmux_capture_pane() - except Exception: + except Exception: # pylint: disable=broad-except # Ignore pass @@ -450,7 +456,7 @@ class RecoveryState(): minutes=int(minutes), seconds=int(seconds), ) - except Exception: + except Exception: # pylint: disable=broad-except # Ignore and leave as raw string pass @@ -460,15 +466,16 @@ class RecoveryState(): now = datetime.datetime.now(tz=self.timezone) _etoc = now + etoc_delta self.etoc = _etoc.strftime('%Y-%m-%d %H:%M %Z') - except Exception: + except Exception: # pylint: disable=broad-except # Ignore and leave as current string pass def update_progress(self): + # pylint: disable=attribute-defined-outside-init """Update overall progress using block_pairs.""" self.rescued = 0 - for bp in self.block_pairs: - self.rescued += bp.rescued + for b_p in self.block_pairs: + self.rescued += b_p.rescued self.rescued_percent = (self.rescued / self.total_size) * 100 self.status_percent = get_formatted_status( label='Recovered:', data=self.rescued_percent) @@ -514,10 +521,13 @@ def create_path_obj(path): def double_confirm_clone(): """Display warning and get 2nd confirmation, returns bool.""" print_standard('\nSAFETY CHECK') - print_warning('All data will be DELETED from the ' - 'destination device and partition(s) listed above.') - print_warning('This is irreversible and will lead ' - 'to {CLEAR}{RED}DATA LOSS.'.format(**COLORS)) + print_warning( + 'All data will be DELETED from the ' + 'destination device and partition(s) listed above.' + ) + print_warning( + 'This is irreversible and will lead to {CLEAR}{RED}DATA LOSS.'.format( + **COLORS)) return ask('Asking again to confirm, is this correct?') @@ -677,13 +687,13 @@ def get_dir_report(dir_path): output.append('{BLUE}{label:<{width}}{line}{CLEAR}'.format( label='PATH', width=width, - line=line.replace('\n',''), + line=line.replace('\n', ''), **COLORS)) else: output.append('{path:<{width}}{line}'.format( path=dir_path, width=width, - line=line.replace('\n',''))) + line=line.replace('\n', ''))) # Done return '\n'.join(output) @@ -700,13 +710,15 @@ def get_formatted_status(label, data): data_width = SIDE_PANE_WIDTH - len(label) try: data_str = '{data:>{data_width}.2f} %'.format( - data=data, - data_width=data_width-2) + data=data, + data_width=data_width-2, + ) except ValueError: # Assuming non-numeric data data_str = '{data:>{data_width}}'.format( - data=data, - data_width=data_width) + data=data, + data_width=data_width, + ) status = '{label}{s_color}{data_str}{CLEAR}'.format( label=label, s_color=get_status_color(data), @@ -742,9 +754,9 @@ def is_writable_dir(dir_obj): """Check if we have read-write-execute permissions, returns bool.""" is_ok = True path_st_mode = os.stat(dir_obj.path).st_mode - is_ok == is_ok and path_st_mode & stat.S_IRUSR - is_ok == is_ok and path_st_mode & stat.S_IWUSR - is_ok == is_ok and path_st_mode & stat.S_IXUSR + is_ok &= path_st_mode & stat.S_IRUSR + is_ok &= path_st_mode & stat.S_IWUSR + is_ok &= path_st_mode & stat.S_IXUSR return is_ok @@ -818,16 +830,15 @@ def menu_main(state): # Build menu main_options = [ {'Base Name': 'Auto continue (if recovery % over threshold)', - 'Enabled': True}, + 'Enabled': True}, {'Base Name': 'Retry (mark non-rescued sectors "non-tried")', - 'Enabled': False}, + 'Enabled': False}, {'Base Name': 'Reverse direction', 'Enabled': False}, ] actions = [ {'Name': 'Start', 'Letter': 'S'}, - {'Name': 'Change settings {YELLOW}(experts only){CLEAR}'.format( - **COLORS), - 'Letter': 'C'}, + {'Name': 'Change settings {YELLOW}(experts only){CLEAR}'.format(**COLORS), + 'Letter': 'C'}, {'Name': 'Quit', 'Letter': 'Q', 'CRLF': True}, ] @@ -887,7 +898,7 @@ def menu_main(state): state.current_pass_min() < AUTO_PASS_1_THRESHOLD): auto_run = False elif (state.current_pass == 1 and - state.current_pass_min() < AUTO_PASS_2_THRESHOLD): + state.current_pass_min() < AUTO_PASS_2_THRESHOLD): auto_run = False else: auto_run = False @@ -1019,8 +1030,8 @@ def run_ddrescue(state, pass_settings): fix_tmux_panes(state, forced=True) # Run pass for each block-pair - for bp in state.block_pairs: - if bp.pass_done[state.current_pass]: + for b_p in state.block_pairs: + if b_p.pass_done[state.current_pass]: # Skip to next block-pair continue update_sidepane(state) @@ -1028,7 +1039,7 @@ def run_ddrescue(state, pass_settings): # Set ddrescue cmd cmd = [ 'ddrescue', *pass_settings, - bp.source_path, bp.dest_path, bp.map_path] + b_p.source_path, b_p.dest_path, b_p.map_path] if state.mode == 'clone': cmd.append('--force') if state.current_pass == 0: @@ -1043,7 +1054,7 @@ def run_ddrescue(state, pass_settings): # Start ddrescue try: clear_screen() - print_info('Current dev: {}'.format(bp.source_path)) + print_info('Current dev: {}'.format(b_p.source_path)) ddrescue_proc = popen_program(cmd) i = 0 while True: @@ -1052,13 +1063,13 @@ def run_ddrescue(state, pass_settings): state.smart_source.get_smart_details() with open(state.smart_out, 'w') as f: report = state.smart_source.generate_attribute_report( - timestamp=True) + timestamp=True) for line in report: f.write('{}\n'.format(line)) i += 1 # Update progress - bp.update_progress(state.current_pass) + b_p.update_progress(state.current_pass) update_sidepane(state) # Fix panes @@ -1068,11 +1079,11 @@ def run_ddrescue(state, pass_settings): try: ddrescue_proc.wait(timeout=1) sleep(2) - bp.update_progress(state.current_pass) + b_p.update_progress(state.current_pass) update_sidepane(state) break except subprocess.TimeoutExpired: - # Catch to update smart/bp/sidepane + # Catch to update smart/b_p/sidepane pass except KeyboardInterrupt: @@ -1081,7 +1092,7 @@ def run_ddrescue(state, pass_settings): ddrescue_proc.wait(timeout=10) # Update progress/sidepane again - bp.update_progress(state.current_pass) + b_p.update_progress(state.current_pass) update_sidepane(state) # Was ddrescue aborted? @@ -1103,7 +1114,7 @@ def run_ddrescue(state, pass_settings): break else: # Mark pass finished - bp.finish_pass(state.current_pass) + b_p.finish_pass(state.current_pass) update_sidepane(state) # Done @@ -1378,14 +1389,14 @@ def update_sidepane(state): output.append('─────────────────────') # Source(s) progress - for bp in state.block_pairs: + for b_p in state.block_pairs: if state.source.is_image(): output.append('{BLUE}Image File{CLEAR}'.format(**COLORS)) else: output.append('{BLUE}{source}{CLEAR}'.format( - source=bp.source_path, + source=b_p.source_path, **COLORS)) - output.extend(bp.status) + output.extend(b_p.status) output.append(' ') # EToC @@ -1410,5 +1421,3 @@ def update_sidepane(state): if __name__ == '__main__': print("This file is not meant to be called directly.") - -# vim: sts=2 sw=2 ts=2