def interactive(): session = PromptSession( completer=DshellCompleter.from_nested_dict(nested_dict), history=get_history('main', InMemoryHistory()), clipboard=PyperclipClipboard(), enable_history_search=True, enable_suspend=True) parser = ArgumentParserRaise(allow_abbrev=False, prog='') parser = create_parser(nested_dict, parser) while True: message = [ ('class:username', env._username if env._username else "?"), ('class:at', '@'), ('class:host', env.get("SERVER") if env.get("SERVER") else "?"), ('', ':'), ('class:path', 'dshell'), ('', '> '), ] try: text = session.prompt(message, style=style) except KeyboardInterrupt: continue # Control-C pressed. Try again. except EOFError: exit_dshell() if text.startswith('!'): subprocess.call(text.lstrip('!'), shell=True) else: try: namespace = parser.parse_args(shlex.split(text)) except (ValueError, argparse.ArgumentError) as e: dprint(e) continue except SystemExit: continue except Exception as e: dprint(e) continue else: cmd_params = vars(namespace) if not text: continue elif text == 'help': parser.print_usage() elif text and len(cmd_params) == 0: try: parser.parse_args(shlex.split(text) + ['-h']) except SystemExit: continue else: call_func_with_signature(cmd_params)
def login(username=None, password=None, save=False): try: ntwrk.login(username, password) except requests.exceptions.ConnectionError as e: dprint( f"Unable to contact with {environ.get('SCHEME')}://{environ.get('SERVER')}:{environ.get('PORT')}/" ) except Exception as e: dprint(str(e)) else: if save: save_config_file(os.path.expanduser(env.get('CONFIG_FILE', None)), username=env._username, token=env._refresh_token, server=env.get('SERVER'), port=env.get('PORT'))
def get_history(tag, default=None): file_history = environ.get('FILE_HISTORY', None) if file_history: file_history = os.path.expanduser('~/.dshell_history') if not os.path.exists(file_history): open(file_history, 'w').close() history = FileTagHistory(file_history, tag) else: history = default return history
def generate_url(view, view_data, ip=None, port=defaults.DEFAULT_PORT, scheme='https'): try: path = view_path_map[view] except KeyError: raise RuntimeError(f"'{view}' not set in metadata") path = _replace_path_args(path, view_data or {}) if (env.get('SERVER', ip) or ip) is None: raise ValueError('No SERVER specified.') return f"{env.get('SCHEME', scheme) or scheme}://" \ f"{env.get('SERVER', ip) or ip}:" \ f"{env.get('PORT', port) or port}" \ f"{path}"
def main(): ch = logging.StreamHandler() logger = logging.getLogger('dshell') logger.addHandler(ch) # parse args args = docopt(__doc__, version='dshell version 1.0', options_first=True) bootstrap_environ(args) # process args argv = [args['COMMAND']] + args['ARGS'] if not ('-h' or '--help') in argv: if args['COMMAND'] is None: import dimensigon.dshell dimensigon.dshell.INTERACTIVE = True interactive() else: if env._refresh_token is None: exit('No token specified. Unable to run command') if not env.get('SERVER', None): exit('No server specified. Unable to run command') if args['COMMAND'] in commands: parser = create_parser({args['COMMAND']: nested_dict[args['COMMAND']]}, parser=ArgumentParser(prog="dshell")) namespace = parser.parse_args(argv) if hasattr(namespace, 'func'): call_func_with_signature(vars(namespace)) elif args['COMMAND'] in batch_commands: module = importlib.import_module('.dshell_%s' % args['COMMAND'], 'dimensigon.dshell.batch') module.main(argv) else: exit("%r is not a dshell command. See 'dshell --help'." % args['COMMAND']) else: parser = create_parser({args['COMMAND']: nested_dict[args['COMMAND']]}, parser=ArgumentParser(prog="dshell")) parser.parse_args(argv)
def dprint(msg): if isinstance(msg, str): if msg not in ('\n', None, ''): print(msg) elif isinstance(msg, Response): if msg.code: dprint(msg.msg) else: dprint(msg.exception) elif isinstance(msg, Exception): if env.get('DEBUG'): dprint(format_exception(msg)) else: dprint(str(msg) if str(msg) else msg.__class__.__name__) else: try: tokens = list( pygments.lex(json.dumps(msg, indent=2), lexer=JSONLexer())) except: pprint(msg) else: print_formatted_text(PygmentsTokens(tokens), end="")
def login(username=None, password=None): if not username: if not env._username: try: username = prompt("Username: "******"Password: ", is_password=True) except KeyboardInterrupt: return resp = requests.post(generate_url('root.login', {}), json={ 'username': username, 'password': password }, verify=False) resp.raise_for_status() env._username = username env._access_token = resp.json()['access_token'] env._refresh_token = resp.json()['refresh_token'] file = os.path.expanduser(env.get('CONFIG_FILE', None)) if file and os.path.exists(file): config = configparser.ConfigParser() config.read(file) if config.has_section('AUTH') and config.has_section('REMOTE'): if config['AUTH'].get('username') == env._username: from dimensigon.dshell.bootstrap import save_config_file del config save_config_file(token=env._refresh_token)
def request(method, url, session=None, token_refreshed=False, login=True, **kwargs) -> Response: exception = None content = None status = None json_data = None headers = {} if not session: _session = requests.session() else: _session = session raise_on_error = kwargs.pop('raise_on_error', False) func = getattr(_session, method.lower()) if 'auth' not in kwargs: if env._access_token is None: try: refresh_access_token(login_=login) except requests.exceptions.ConnectionError as e: return Response(exception=ConnectionError( f"Unable to contact with {env.get('SCHEME')}://" f"{env.get('SERVER')}:{env.get('PORT')}/refresh"), url=url) except Exception as e: return Response(exception=e, url=url) else: if env._access_token is None: return Response( exception=ValueError("No authentication set"), url=url) kwargs['auth'] = HTTPBearerAuth(env._access_token) if 'headers' not in kwargs: kwargs['headers'] = {} kwargs['headers'].update({'D-Securizer': 'plain'}) kwargs['verify'] = env.get('SSL_VERIFY') logger.debug(f"{method.upper()} {url}\n{kwargs}") resp = None try: resp: requests.Response = func(url, **kwargs) except (requests.Timeout, ) as e: timeout = kwargs.get('timeout', None) if isinstance(timeout, tuple): timeout = timeout[0] + timeout[1] exception = TimeoutError( f"Socket timeout reached while trying to connect to {url} " f"for {timeout} seconds") except requests.ConnectionError as e: exception = ConnectionError(f"Unable to contact to {url}") except Exception as e: exception = e finally: if session is None and not (getattr(resp, 'status_code', None) == 401 and resp.json().get('msg') == 'Token has expired'): _session.close() if exception is None: status = resp.status_code headers = resp.headers if status == 401 and not token_refreshed: json_data = resp.json() if json_data.get('msg') == 'Token has expired': try: refresh_access_token() except requests.exceptions.ConnectionError as e: return Response(exception=ConnectionError( f"Unable to contact with {env.get('SCHEME')}://" f"{env.get('SERVER')}:{env.get('PORT')}/refresh"), url=url) kwargs['auth'] = HTTPBearerAuth(env._access_token) resp = request(method, url, session=_session, token_refreshed=True, **kwargs) if not session: _session.close() return resp try: json_data = resp.json() except (ValueError, ): content = resp.text if json_data is not None: # try: # content = unpack_msg(json_data) # except NotValidMessage: # content = json_data content = json_data else: if raise_on_error: raise exception return Response(msg=content, code=status, exception=exception, url=url, headers=headers)