class HILApi: def __init__(self, module, conn): self.api = API(module) self.conn = conn self.running = False def __del__(self): self.stop() def start(self, port = 8000): """ Start the api server """ self.api.directive('conn', self.conn) self.api.http.add_middleware(HILApiMiddleware(self.conn)) if not self.running: print("=> Application starting on 0.0.0.0:{0}".format(port)) print("=> Ctrl-C to shutdown server\n") sv = self.api.http.server() httpd = make_server('', port, sv) self.__server_process = Process(target=httpd.serve_forever) self.__server_process.start() self.running = True def stop(self): """ Stop the api server """ if self.running: self.__server_process.terminate() self.__server_process.join() self.running = False
def __init__(self, api, version=None, headers=empty.dict, timeout=None, raise_on=(500, ), **kwargs): super().__init__(timeout=timeout, raise_on=raise_on, version=version, **kwargs) self.api = API(api) self.headers = headers
def call(method, api_or_module, url, body='', headers=None, params=None, query_string='', scheme='http', **kwargs): """Simulates a round-trip call against the given API / URL""" api = API(api_or_module).http.server() response = StartResponseMock() headers = {} if headers is None else headers if not isinstance(body, str) and 'json' in headers.get('content-type', 'application/json'): body = output_format.json(body) headers.setdefault('content-type', 'application/json') params = params if params else {} params.update(kwargs) if params: query_string = '{}{}{}'.format(query_string, '&' if query_string else '', urlencode(params, True)) result = api(create_environ(path=url, method=method, headers=headers, query_string=query_string, body=body, scheme=scheme), response) if result: try: response.data = result[0].decode('utf8') except TypeError: response.data = [] for chunk in result: response.data.append(chunk.decode('utf8')) response.data = "".join(response.data) except UnicodeDecodeError: response.data = result[0] response.content_type = response.headers_dict['content-type'] if response.content_type == 'application/json': response.data = json.loads(response.data) return response
def call(method, api_or_module, url, body='', headers=None, **params): """Simulates a round-trip call against the given API / URL""" api = API(api_or_module).http.server() response = StartResponseMock() if not isinstance(body, str): body = output_format.json(body) headers = {} if headers is None else headers headers.setdefault('content-type', 'application/json') result = api( create_environ(path=url, method=method, headers=headers, query_string=urlencode(params), body=body), response) if result: try: response.data = result[0].decode('utf8') except TypeError: response.data = [] for chunk in result: response.data.append(chunk.decode('utf8')) response.data = "".join(response.data) except UnicodeDecodeError: response.data = result[0] response.content_type = response.headers_dict['content-type'] if response.content_type == 'application/json': response.data = json.loads(response.data) return response
def hug(file: 'A Python file that contains a Hug API'=None, module: 'A Python module that contains a Hug API'=None, host: 'Interface to bind to'='', port: number=8000, no_404_documentation: boolean=False, manual_reload: boolean=False, interval: number=1, command: 'Run a command defined in the given module'=None, silent: boolean=False): """Hug API Development Server""" api_module = None if file and module: print("Error: can not define both a file and module source for Hug API.") sys.exit(1) if file: sys.path.append(os.path.dirname(os.path.abspath(file))) sys.path.append(os.getcwd()) api_module = importlib.machinery.SourceFileLoader(file.split(".")[0], file).load_module() elif module: sys.path.append(os.getcwd()) api_module = importlib.import_module(module) if not api_module or not hasattr(api_module, '__hug__'): print("Error: must define a file name or module that contains a Hug API.") sys.exit(1) api = API(api_module, display_intro=not silent) if command: if command not in api.cli.commands: print(str(api.cli)) sys.exit(1) sys.argv[1:] = sys.argv[(sys.argv.index('-c') if '-c' in sys.argv else sys.argv.index('--command')) + 2:] api.cli.commands[command]() return ran = False if not manual_reload: thread.start_new_thread(reload_checker, (interval, )) while True: reload_checker.reloading = False time.sleep(1) try: _start_api(api_module, host, port, no_404_documentation, False if silent else not ran) except KeyboardInterrupt: if not reload_checker.reloading: sys.exit(1) reload_checker.reloading = False ran = True for module in [name for name in sys.modules.keys() if name not in INIT_MODULES]: del(sys.modules[module]) if file: api_module = importlib.machinery.SourceFileLoader(file.split(".")[0], file).load_module() elif module: api_module = importlib.import_module(module) else: _start_api(api_module, host, port, no_404_documentation, not ran)
def hug(file: 'A Python file that contains a Hug API' = None, module: 'A Python module that contains a Hug API' = None, port: number = 8000, no_404_documentation: boolean = False, command: 'Run a command defined in the given module' = None): """Hug API Development Server""" api_module = None if file and module: print( "Error: can not define both a file and module source for Hug API.") sys.exit(1) if file: sys.path.append(os.path.dirname(os.path.abspath(file))) sys.path.append(os.getcwd()) api_module = importlib.machinery.SourceFileLoader( file.split(".")[0], file).load_module() elif module: api_module = importlib.import_module(module) if not api_module or not hasattr(api_module, '__hug__'): print( "Error: must define a file name or module that contains a Hug API." ) sys.exit(1) api = API(api_module) if command: if command not in api.cli.commands: print(str(api.cli)) sys.exit(1) sys.argv[1:] = sys.argv[(sys.argv.index('-c') if '-c' in sys.argv else sys.argv.index('--command')) + 2:] api.cli.commands[command]() return API(api_module).http.serve(port, no_404_documentation)
def cli(method, *args, api=None, module=None, **arguments): """Simulates testing a hug cli method from the command line""" collect_output = arguments.pop('collect_output', True) if api and module: raise ValueError( "Please specify an API OR a Module that contains the API, not both" ) elif api or module: method = API(api or module).cli.commands[method].interface._function command_args = [method.__name__] + list(args) for name, values in arguments.items(): if not isinstance(values, (tuple, list)): values = (values, ) for value in values: command_args.append('--{0}'.format(name)) if not value in (True, False): command_args.append('{0}'.format(value)) old_sys_argv = sys.argv sys.argv = [str(part) for part in command_args] old_outputs = method.interface.cli.outputs if collect_output: method.interface.cli.outputs = lambda data: to_return.append( old_outputs(data)) to_return = [] try: method.interface.cli() except Exception as e: to_return = (e, ) method.interface.cli.outputs = old_outputs sys.argv = old_sys_argv if to_return: result = _internal_result(to_return) try: result = json.loads(result) except Exception: try: result = ast.literal_eval(result) except Exception: pass return result
def call(method, api_or_module, url, body="", headers=None, params=None, query_string="", scheme="http", host=DEFAULT_HOST, **kwargs): """Simulates a round-trip call against the given API / URL""" api = API(api_or_module).http.server() response = StartResponseMock() headers = {} if headers is None else headers if not isinstance(body, str) and "json" in headers.get( "content-type", "application/json"): body = output_format.json(body) headers.setdefault("content-type", "application/json") params = params if params else {} params.update(kwargs) if params: query_string = "{}{}{}".format(query_string, "&" if query_string else "", urlencode(params, True)) result = api( create_environ( path=url, method=method, headers=headers, query_string=query_string, body=body, scheme=scheme, host=host, ), response, ) if result: response.data = _internal_result(result) response.content_type = response.headers_dict["content-type"] if "application/json" in response.content_type: response.data = json.loads(response.data) return response
class Local(Service): __slots__ = ('api', 'headers') def __init__(self, api, version=None, headers=empty.dict, timeout=None, raise_on=(500, ), **kwargs): super().__init__(timeout=timeout, raise_on=raise_on, version=version, **kwargs) self.api = API(api) self.headers = headers def request(self, method, url, url_params=empty.dict, headers=empty.dict, timeout=None, **params): function = self.api.http.versioned.get(self.version, {}).get(url, None) if not function: function = self.api.http.versioned.get(None, {}).get(url, None) if not function: if 404 in self.raise_on: raise requests.HTTPError('404 Not Found occured for url: {0}'.format(url)) return Response('Not Found', 404, {'content-type', 'application/json'}) interface = function.interface.http response = falcon.Response() request = Request(None, None, empty.dict) context = self.api.context_factory(api=self.api, api_version=self.version, interface=interface) interface.set_response_defaults(response) params.update(url_params) params = interface.gather_parameters(request, response, context, api_version=self.version, **params) errors = interface.validate(params, context) if errors: interface.render_errors(errors, request, response) else: interface.render_content(interface.call_function(params), context, request, response) data = BytesIO(response.data) content_type, content_params = parse_content_type(response._headers.get('content-type', '')) if content_type in input_format: data = input_format[content_type](data, **content_params) status_code = int(''.join(re.findall('\d+', response.status))) if status_code in self.raise_on: raise requests.HTTPError('{0} occured for url: {1}'.format(response.status, url)) return Response(data, status_code, response._headers)
def _start_api(api_module, host, port, no_404_documentation, show_intro=True): API(api_module).http.serve(host, port, no_404_documentation, show_intro)
def __init__(self, api, version=None, headers=empty.dict, timeout=None, raise_on=(500, ), **kwargs): super().__init__(timeout=timeout, raise_on=raise_on, version=version, **kwargs) self.api = API(api) self.headers = headers
class Local(Service): __slots__ = ("api", "headers") def __init__(self, api, version=None, headers=empty.dict, timeout=None, raise_on=(500, ), **kwargs): super().__init__(timeout=timeout, raise_on=raise_on, version=version, **kwargs) self.api = API(api) self.headers = headers def request(self, method, url, url_params=empty.dict, headers=empty.dict, timeout=None, **params): function = self.api.http.versioned.get(self.version, {}).get(url, None) if not function: function = self.api.http.versioned.get(None, {}).get(url, None) if not function: if 404 in self.raise_on: raise requests.HTTPError( "404 Not Found occured for url: {0}".format(url)) return Response("Not Found", 404, {"content-type", "application/json"}) interface = function.interface.http response = falcon.Response() request = Request(None, None, empty.dict) context = self.api.context_factory(api=self.api, api_version=self.version, interface=interface) interface.set_response_defaults(response) params.update(url_params) params = interface.gather_parameters(request, response, context, api_version=self.version, **params) errors = interface.validate(params, context) if errors: interface.render_errors(errors, request, response) else: interface.render_content(interface.call_function(params), context, request, response) data = BytesIO(response.data) content_type, content_params = parse_content_type( response._headers.get("content-type", "")) if content_type in input_format: data = input_format[content_type](data, **content_params) status_code = int("".join(re.findall("\d+", response.status))) if status_code in self.raise_on: raise requests.HTTPError("{0} occured for url: {1}".format( response.status, url)) return Response(data, status_code, response._headers)
def __init__(self, module, conn): self.api = API(module) self.conn = conn self.running = False
def hug(file: 'A Python file that contains a Hug API' = None, module: 'A Python module that contains a Hug API' = None, port: number = 8000, no_404_documentation: boolean = False, manual_reload: boolean = False, interval: number = 1, command: 'Run a command defined in the given module' = None): """Hug API Development Server""" api_module = None if file and module: print( "Error: can not define both a file and module source for Hug API.") sys.exit(1) if file: sys.path.append(os.path.dirname(os.path.abspath(file))) sys.path.append(os.getcwd()) api_module = importlib.machinery.SourceFileLoader( file.split(".")[0], file).load_module() elif module: api_module = importlib.import_module(module) if not api_module or not hasattr(api_module, '__hug__'): print( "Error: must define a file name or module that contains a Hug API." ) sys.exit(1) api = API(api_module) if command: if command not in api.cli.commands: print(str(api.cli)) sys.exit(1) sys.argv[1:] = sys.argv[(sys.argv.index('-c') if '-c' in sys.argv else sys.argv.index('--command')) + 2:] api.cli.commands[command]() return if manual_reload: _start_api(api_module, port, no_404_documentation) else: is_running = True ran = False while is_running: try: running = Process(target=_start_api, args=(api_module, port, no_404_documentation, not ran)) running.start() files = {} for module in list(sys.modules.values()): path = getattr(module, '__file__', '') if path[-4:] in ('.pyo', '.pyc'): path = path[:-1] if path and exists(path): files[path] = os.stat(path).st_mtime changed = False while not changed: for path, last_modified in files.items(): if not exists(path): print( '\n> Reloading due to file removal: {}'.format( path)) changed = True elif os.stat(path).st_mtime > last_modified: print( '\n> Reloading due to file change: {}'.format( path)) changed = True if changed: running.terminate() for module in [ name for name in sys.modules.keys() if name not in INIT_MODULES ]: del (sys.modules[module]) if file: api_module = importlib.machinery.SourceFileLoader( file.split(".")[0], file).load_module() elif module: api_module = importlib.import_module(module) ran = True break time.sleep(interval) except KeyboardInterrupt: is_running = False