diff --git a/client/main/dpcs b/client/main/dpcs index a680195..625ca7c 100755 --- a/client/main/dpcs +++ b/client/main/dpcs @@ -7,13 +7,24 @@ from random import sample from string import ascii_lowercase from string import ascii_uppercase from string import digits +import errno import json import subprocess import sys from requests import get from requests import post +from requests import ConnectionError from requests import RequestException +from thefuck import const as thefuck_const +from thefuck import logs as thefuck_logs +from thefuck.conf import settings as thefuck_settings +from thefuck.corrector import get_rules +from thefuck.corrector import organize_commands +from thefuck.exceptions import NoRuleMatched +from thefuck.types import Command +from thefuck.ui import read_actions +from thefuck.ui import CommandSelector from dpcs_client.settings import read_settings from dpcs_client.systemcheck import systemcheck @@ -21,7 +32,7 @@ from dpcs_client.systemcheck import systemcheck EXIT_OK = 0 -def generate_report(exit_code, stderr_output): +def generate_report(exit_code, stderr_output, script): """Generate a report which will be sent to the DCPS server. Arguments @@ -32,6 +43,9 @@ def generate_report(exit_code, stderr_output): stderr_output : string The output written on stderr by the failed process + script : string + The script run by user + Return ------ template : dict @@ -40,8 +54,8 @@ def generate_report(exit_code, stderr_output): template = { "crash_report": { "application": { - # TO DO - implementation depends on the way how the daemon is - # implemented + 'name': script, + 'version': "" }, "system_info": {}, "exit_code": exit_code, @@ -75,6 +89,29 @@ def handle_request_error(exception, dpcs_message): print(exception.response.text, file=sys.stderr) +def handle_script(script): + """Show interactive question. + + Arguments + --------- + script : string + The solution script. + """ + + print("How would you like to use this solution?") + resp = '' + while resp != 'q' and resp != 'r' and resp != 's' and resp != 'p': + resp = raw_input("(q) - ignore & quit, (r) - run, " + + "(s) - save, (p) - print\n") + + if resp == 's': + save_script(script) + elif resp == 'r': + run_script(script) + elif resp == 'p': + print(script) + + def rand_fname(parent_path, prefix, suffix, length=4): """Create a random filename for storing the solution script. @@ -143,6 +180,56 @@ def save_script(script): print("The script produced by DPCS is available in " + filename) + +def try_the_fuck(script, stout, sterr): + """Use thefuck library internals to solve easy problems + + Arguments + --------- + script : string + The command given by the user + + stout : string + Script's standard output. + + sterr : string + Script's error output. + """ + thefuck_settings.init() + command = Command(script=script, stdout=stout, stderr=sterr) + + # Removes history rule in order to prevent running dpcs recursively + rules = filter(lambda rule: rule.name != 'history', get_rules()) + + corrected_commands = organize_commands(( + corrected for rule in rules + if rule.is_match(command) + for corrected in rule.get_corrected_commands(command) + )) + + try: + selector = CommandSelector(corrected_commands) + except NoRuleMatched: + return + + thefuck_logs.confirm_text(selector.value) + + for action in read_actions(): + if action == thefuck_const.ACTION_SELECT: + sys.stderr.write('\n') + handle_script(selector.value.script) + exit(0) + elif action == thefuck_const.ACTION_ABORT: + sys.stderr.write('\n') + return + elif action == thefuck_const.ACTION_PREVIOUS: + selector.previous() + thefuck_logs.confirm_text(selector.value) + elif action == thefuck_const.ACTION_NEXT: + selector.next() + thefuck_logs.confirm_text(selector.value) + + if __name__ == '__main__': if len(sys.argv) != 2: @@ -152,24 +239,31 @@ if __name__ == '__main__': server_address = read_settings()['server_address'] p = subprocess.Popen(sys.argv[1], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - _, output = p.communicate() + stout, sterr = p.communicate() code = p.returncode - print(output) + # TO IMPROVE: the code below will change the order of printing + print(stout, end="") + print(sterr, end="") if code != EXIT_OK: + try_the_fuck(sys.argv[1], stout, sterr) + api_description_url = server_address + "vd1/paths/" try: response = get(api_description_url) + except ConnectionError as e: + print("Error: DPCS coudln't connect with the server") + exit(errno.EHOSTUNREACH) except RequestException as e: - #handle_request_error( - # e, "DPCS couldn't get api description" - #) - print("DPCS server: Offline") - exit(2) + handle_request_error( + e, "DPCS couldn't get api description" + ) + exit(errno.EHOSTDOWN) api_paths = response.json() crash_report_url = server_address + api_paths["crash-reports"] @@ -178,7 +272,7 @@ if __name__ == '__main__': 'Content-Type': 'application/json' } - report = generate_report(code, output) + report = generate_report(code, sterr) try: response = post(crash_report_url, @@ -188,7 +282,7 @@ if __name__ == '__main__': handle_request_error( e, "DPCS couldn't post crash information" ) - exit(3) + exit(errno.EINVAL) script = '#No known solution have been found' if 'crash_report_ack' in response.json(): @@ -196,15 +290,4 @@ if __name__ == '__main__': 'solution']['shell_script'] print("DPCS might have found a solution to your problem!") - print("How would you like to use it?") - resp = '' - while resp != 'q' and resp != 'r' and resp != 's' and resp != 'p': - resp = raw_input("(q) - ignore & quit, (r) - run, " + - "(s) - save, (p) - print\n") - - if resp == 's': - save_script(script) - elif resp == 'r': - run_script(script) - elif resp == 'p': - print(script) + handle_script(script)