From 0aa0bd5a8fbd1167b3376f8395ea215a1cc46ad9 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 19:38:09 -0700 Subject: [PATCH 01/16] changes to make flake8 happy --- examples/cli.py | 2 +- examples/multi_file_cli/api.py | 2 +- examples/multi_file_cli/sub_api.py | 2 +- examples/on_startup.py | 2 +- examples/override_404.py | 2 +- examples/quick_start/first_step_1.py | 2 +- examples/quick_start/first_step_2.py | 2 +- examples/quick_start/first_step_3.py | 4 +- examples/secure_auth_with_db_example.py | 6 +- examples/sink_example.py | 2 +- examples/sqlalchemy_example/demo/app.py | 2 +- examples/static_serve.py | 2 +- examples/write_once.py | 4 +- hug/__init__.py | 14 +-- hug/api.py | 24 ++--- hug/development_runner.py | 4 +- hug/interface.py | 14 +-- hug/json_module.py | 2 +- hug/middleware.py | 4 +- hug/output_format.py | 2 +- hug/route.py | 68 +++++++------- hug/routing.py | 4 +- requirements/build_common.txt | 5 + tests/module_fake.py | 8 +- tests/module_fake_http_and_cli.py | 2 +- tests/test_api.py | 2 +- tests/test_async.py | 2 +- tests/test_context_factory.py | 24 ++--- tests/test_coroutines.py | 2 +- tests/test_decorators.py | 120 ++++++++++++------------ tests/test_directives.py | 12 +-- tests/test_interface.py | 4 +- tests/test_test.py | 2 +- tox.ini | 3 + 34 files changed, 185 insertions(+), 171 deletions(-) diff --git a/examples/cli.py b/examples/cli.py index efb6a094..5ce1a393 100644 --- a/examples/cli.py +++ b/examples/cli.py @@ -2,7 +2,7 @@ import hug -@hug.cli(version="1.0.0") +@hug.CLIRouter(version="1.0.0") def cli(name: "The name", age: hug.types.number): """Says happy birthday to a user""" return "Happy {age} Birthday {name}!\n".format(**locals()) diff --git a/examples/multi_file_cli/api.py b/examples/multi_file_cli/api.py index f7242804..885f7343 100644 --- a/examples/multi_file_cli/api.py +++ b/examples/multi_file_cli/api.py @@ -3,7 +3,7 @@ import sub_api -@hug.cli() +@hug.CLIRouter() def echo(text: hug.types.text): return text diff --git a/examples/multi_file_cli/sub_api.py b/examples/multi_file_cli/sub_api.py index 20ffa319..f550a14f 100644 --- a/examples/multi_file_cli/sub_api.py +++ b/examples/multi_file_cli/sub_api.py @@ -1,6 +1,6 @@ import hug -@hug.cli() +@hug.CLIRouter() def hello(): return "Hello world" diff --git a/examples/on_startup.py b/examples/on_startup.py index c6a59744..d4ffaa85 100644 --- a/examples/on_startup.py +++ b/examples/on_startup.py @@ -16,7 +16,7 @@ def add_more_data(api): data.append("Even subsequent calls") -@hug.cli() +@hug.CLIRouter() @hug.get() def test(): """Returns all stored data""" diff --git a/examples/override_404.py b/examples/override_404.py index 261d6f14..ca3b3d07 100644 --- a/examples/override_404.py +++ b/examples/override_404.py @@ -6,6 +6,6 @@ def hello_world(): return "Hello world!" -@hug.not_found() +@hug.NotFoundRouter() def not_found(): return {"Nothing": "to see"} diff --git a/examples/quick_start/first_step_1.py b/examples/quick_start/first_step_1.py index 971ded8f..d28ad11f 100644 --- a/examples/quick_start/first_step_1.py +++ b/examples/quick_start/first_step_1.py @@ -2,7 +2,7 @@ import hug -@hug.local() +@hug.LocalRouter() def happy_birthday(name: hug.types.text, age: hug.types.number, hug_timer=3): """Says happy birthday to a user""" return {"message": "Happy {0} Birthday {1}!".format(age, name), "took": float(hug_timer)} diff --git a/examples/quick_start/first_step_2.py b/examples/quick_start/first_step_2.py index ee314ae5..0907e77d 100644 --- a/examples/quick_start/first_step_2.py +++ b/examples/quick_start/first_step_2.py @@ -3,7 +3,7 @@ @hug.get(examples="name=Timothy&age=26") -@hug.local() +@hug.LocalRouter() def happy_birthday(name: hug.types.text, age: hug.types.number, hug_timer=3): """Says happy birthday to a user""" return {"message": "Happy {0} Birthday {1}!".format(age, name), "took": float(hug_timer)} diff --git a/examples/quick_start/first_step_3.py b/examples/quick_start/first_step_3.py index 33a02c92..b206162d 100644 --- a/examples/quick_start/first_step_3.py +++ b/examples/quick_start/first_step_3.py @@ -2,9 +2,9 @@ import hug -@hug.cli() +@hug.CLIRouter() @hug.get(examples="name=Timothy&age=26") -@hug.local() +@hug.LocalRouter() def happy_birthday(name: hug.types.text, age: hug.types.number, hug_timer=3): """Says happy birthday to a user""" return {"message": "Happy {0} Birthday {1}!".format(age, name), "took": float(hug_timer)} diff --git a/examples/secure_auth_with_db_example.py b/examples/secure_auth_with_db_example.py index e1ce207e..0cb1fb74 100644 --- a/examples/secure_auth_with_db_example.py +++ b/examples/secure_auth_with_db_example.py @@ -36,7 +36,7 @@ def gen_api_key(username): return hash_password(username, salt) -@hug.cli() +@hug.CLIRouter() def authenticate_user(username, password): """ Authenticate a username and password against our database @@ -57,7 +57,7 @@ def authenticate_user(username, password): return False -@hug.cli() +@hug.CLIRouter() def authenticate_key(api_key): """ Authenticate an API key against our database @@ -79,7 +79,7 @@ def authenticate_key(api_key): basic_authentication = hug.authentication.basic(authenticate_user) -@hug.cli() +@hug.CLIRouter() def add_user(username, password): """ CLI Parameter to add a user to the database diff --git a/examples/sink_example.py b/examples/sink_example.py index aadd395f..5577e88a 100644 --- a/examples/sink_example.py +++ b/examples/sink_example.py @@ -6,6 +6,6 @@ import hug -@hug.sink("/all") +@hug.SinkRouter("/all") def my_sink(request): return request.path.replace("/all", "") diff --git a/examples/sqlalchemy_example/demo/app.py b/examples/sqlalchemy_example/demo/app.py index 748ca17d..1118b1f5 100644 --- a/examples/sqlalchemy_example/demo/app.py +++ b/examples/sqlalchemy_example/demo/app.py @@ -17,7 +17,7 @@ def delete_context(context: SqlalchemyContext, exception=None, errors=None, lack context.cleanup(exception) -@hug.local(skip_directives=False) +@hug.LocalRouter(skip_directives=False) def initialize(db: SqlalchemySession): admin = TestUser(username="admin", password="admin") db.add(admin) diff --git a/examples/static_serve.py b/examples/static_serve.py index eac7019a..dc798c0c 100644 --- a/examples/static_serve.py +++ b/examples/static_serve.py @@ -52,7 +52,7 @@ def setup(api=None): fo.write(image) -@hug.static("/static") +@hug.StaticRouter("/static") def my_static_dirs(): """Returns static directory names to be served.""" global tmp_dir_object diff --git a/examples/write_once.py b/examples/write_once.py index b61ee09a..0db9180c 100644 --- a/examples/write_once.py +++ b/examples/write_once.py @@ -3,8 +3,8 @@ import requests -@hug.local() -@hug.cli() +@hug.LocalRouter() +@hug.CLIRouter() @hug.get() def top_post(section: hug.types.one_of(("news", "newest", "show")) = "news"): """Returns the top post from the provided section""" diff --git a/hug/__init__.py b/hug/__init__.py index e40d8508..a2e98873 100644 --- a/hug/__init__.py +++ b/hug/__init__.py @@ -68,23 +68,23 @@ ) from hug.route import ( call, - cli, + CLIRouter, connect, delete, - exception, + ExceptionRouter, get, get_post, head, - http, - local, - not_found, + URLRouter, + LocalRouter, + NotFoundRouter, object, options, patch, post, put, - sink, - static, + SinkRouter, + StaticRouter, trace, ) from hug.types import create as type diff --git a/hug/api.py b/hug/api.py index 0a6c35b1..3fdfab2b 100644 --- a/hug/api.py +++ b/hug/api.py @@ -123,10 +123,10 @@ def urls(self): def handlers(self): """Returns all registered handlers attached to this API""" used = [] - for base_url, mapping in self.routes.items(): - for url, methods in mapping.items(): - for method, versions in methods.items(): - for version, handler in versions.items(): + for _base_url, mapping in self.routes.items(): + for _url, methods in mapping.items(): + for _method, versions in methods.items(): + for _version, handler in versions.items(): if not handler in used: used.append(handler) yield handler @@ -179,15 +179,15 @@ def extend(self, http_api, route="", base_url="", **kwargs): self.versions.update(http_api.versions) base_url = base_url or self.base_url - for router_base_url, routes in http_api.routes.items(): + for _router_base_url, routes in http_api.routes.items(): self.routes.setdefault(base_url, OrderedDict()) for item_route, handler in routes.items(): - for method, versions in handler.items(): - for version, function in versions.items(): + for _method, versions in handler.items(): + for _version, function in versions.items(): function.interface.api = self.api self.routes[base_url].setdefault(route + item_route, {}).update(handler) - for sink_base_url, sinks in http_api.sinks.items(): + for _sink_base_url, sinks in http_api.sinks.items(): for url, sink in sinks.items(): self.add_sink(sink, route + url, base_url=base_url) @@ -344,9 +344,11 @@ def handle_404(request, response, *args, **kwargs): return handle_404 def version_router( - self, request, response, api_version=None, versions={}, not_found=None, **kwargs + self, request, response, api_version=None, versions=None, not_found=None, **kwargs ): """Intelligently routes a request to the correct handler based on the version being requested""" + if versions is None: + versions = {} request_version = self.determine_version(request, api_version) if request_version: request_version = int(request_version) @@ -551,9 +553,9 @@ def add_directive(self, directive): def handlers(self): """Returns all registered handlers attached to this API""" - if getattr(self, "_http"): + if getattr(self, "_http", None): yield from self.http.handlers() - if getattr(self, "_cli"): + if getattr(self, "_cli", None): yield from self.cli.handlers() @property diff --git a/hug/development_runner.py b/hug/development_runner.py index 196f0713..c7fa67c1 100644 --- a/hug/development_runner.py +++ b/hug/development_runner.py @@ -32,7 +32,7 @@ import _thread as thread from hug._version import current from hug.api import API -from hug.route import cli +from hug.route import CLIRouter from hug.types import boolean, number INIT_MODULES = list(sys.modules.keys()) @@ -42,7 +42,7 @@ 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) -@cli(version=current) +@CLIRouter(version=current) def hug( file: "A Python file that contains a Hug API" = None, module: "A Python module that contains a Hug API" = None, diff --git a/hug/interface.py b/hug/interface.py index 0539fbfe..42065774 100644 --- a/hug/interface.py +++ b/hug/interface.py @@ -117,7 +117,7 @@ def __init__(self, function, args=None): self.input_transformations[name] = transformer - def __call__(__hug_internal_self, *args, **kwargs): + def __call__(__hug_internal_self, *args, **kwargs): # noqa: N805 """"Calls the wrapped function, uses __hug_internal_self incase self is passed in as a kwarg from the wrapper""" if not __hug_internal_self.is_coroutine: return __hug_internal_self._function(*args, **kwargs) @@ -270,7 +270,7 @@ def validate(self, input_parameters, context): type_handler, input_parameters[key], context=context ) except InvalidTypeData as error: - errors[key] = error.reasons or str(error.message) + errors[key] = error.reasons or str(error) except Exception as error: if hasattr(error, "args") and error.args: errors[key] = error.args[0] @@ -342,7 +342,7 @@ def _rewrite_params(self, params): @staticmethod def cleanup_parameters(parameters, exception=None): - for parameter, directive in parameters.items(): + for _parameter, directive in parameters.items(): if hasattr(directive, "cleanup"): directive.cleanup(exception=exception) @@ -385,7 +385,7 @@ def __call__(self, *args, **kwargs): context = self.api.context_factory(api=self.api, api_version=self.version, interface=self) """Defines how calling the function locally should be handled""" - for requirement in self.requires: + for _requirement in self.requires: lacks_requirement = self.check_requirements(context=context) if lacks_requirement: self.api.delete_context(context, lacks_requirement=lacks_requirement) @@ -604,7 +604,7 @@ def exit_callback(message): args.extend(pass_to_function.pop(self.additional_options, ())) if self.interface.takes_kwargs: add_options_to = None - for index, option in enumerate(unknown): + for option in unknown: if option.startswith("--"): if add_options_to: value = pass_to_function[add_options_to] @@ -959,9 +959,9 @@ def documentation(self, add_to=None, version=None, prefix="", base_url="", url=" def urls(self, version=None): """Returns all URLS that are mapped to this interface""" urls = [] - for base_url, routes in self.api.http.routes.items(): + for _base_url, routes in self.api.http.routes.items(): for url, methods in routes.items(): - for method, versions in methods.items(): + for _method, versions in methods.items(): for interface_version, interface in versions.items(): if interface_version == version and interface == self: if not url in urls: diff --git a/hug/json_module.py b/hug/json_module.py index 5df4f4ae..f881f7f8 100644 --- a/hug/json_module.py +++ b/hug/json_module.py @@ -5,7 +5,7 @@ if HUG_USE_UJSON: import ujson as json - class dumps_proxy: + class dumps_proxy: # noqa: N801 """Proxies the call so non supported kwargs are skipped and it enables escape_forward_slashes to simulate built-in json """ diff --git a/hug/middleware.py b/hug/middleware.py index 61bd0ffb..68e8d396 100644 --- a/hug/middleware.py +++ b/hug/middleware.py @@ -153,8 +153,10 @@ class CORSMiddleware(object): __slots__ = ("api", "allow_origins", "allow_credentials", "max_age") def __init__( - self, api, allow_origins: list = ["*"], allow_credentials: bool = True, max_age: int = None + self, api, allow_origins: list = None, allow_credentials: bool = True, max_age: int = None ): + if allow_origins is None: + allow_origins = ["*"] self.api = api self.allow_origins = allow_origins self.allow_credentials = allow_credentials diff --git a/hug/output_format.py b/hug/output_format.py index 1d50d38c..6e60dfb3 100644 --- a/hug/output_format.py +++ b/hug/output_format.py @@ -384,7 +384,7 @@ def output_type(data, request, response): handler = default accepted = [accept_quality(accept_type) for accept_type in accept.split(",")] accepted.sort(key=itemgetter(0)) - for quality, accepted_content_type in reversed(accepted): + for _quality, accepted_content_type in reversed(accepted): if accepted_content_type in handlers: handler = handlers[accepted_content_type] break diff --git a/hug/route.py b/hug/route.py index 91eac8a2..1662d209 100644 --- a/hug/route.py +++ b/hug/route.py @@ -27,16 +27,16 @@ from falcon import HTTP_METHODS import hug.api -from hug.routing import CLIRouter as cli -from hug.routing import ExceptionRouter as exception -from hug.routing import LocalRouter as local -from hug.routing import NotFoundRouter as not_found -from hug.routing import SinkRouter as sink -from hug.routing import StaticRouter as static -from hug.routing import URLRouter as http +from hug.routing import CLIRouter as CLIRouter +from hug.routing import ExceptionRouter as ExceptionRouter +from hug.routing import LocalRouter as LocalRouter +from hug.routing import NotFoundRouter as NotFoundRouter +from hug.routing import SinkRouter as SinkRouter +from hug.routing import StaticRouter as StaticRouter +from hug.routing import URLRouter as URLRouter -class Object(http): +class Object(URLRouter): """Defines a router for classes and objects""" def __init__(self, urls=None, accept=HTTP_METHODS, output=None, **kwargs): @@ -61,11 +61,11 @@ def __call__(self, method_or_class=None, **kwargs): http_routes = getattr(argument, "_hug_http_routes", ()) for route in http_routes: - http(**self.where(**route).route)(argument) + URLRouter(**self.where(**route).route)(argument) cli_routes = getattr(argument, "_hug_cli_routes", ()) for route in cli_routes: - cli(**self.where(**route).route)(argument) + CLIRouter(**self.where(**route).route)(argument) return method_or_class @@ -86,14 +86,14 @@ def decorator(class_definition): http_routes = getattr(handler, "_hug_http_routes", ()) if http_routes: for route in http_routes: - http(**router.accept(method).where(**route).route)(handler) + URLRouter(**router.accept(method).where(**route).route)(handler) else: - http(**router.accept(method).route)(handler) + URLRouter(**router.accept(method).route)(handler) cli_routes = getattr(handler, "_hug_cli_routes", ()) if cli_routes: for route in cli_routes: - cli(**self.where(**route).route)(handler) + CLIRouter(**self.where(**route).route)(handler) return class_definition return decorator @@ -119,7 +119,7 @@ def __init__(self, api): def http(self, *args, **kwargs): """Starts the process of building a new HTTP route linked to this API instance""" kwargs["api"] = self.api - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def urls(self, *args, **kwargs): """DEPRECATED: for backwords compatibility with < hug 2.2.0. `API.http` should be used instead. @@ -131,27 +131,27 @@ def urls(self, *args, **kwargs): def not_found(self, *args, **kwargs): """Defines the handler that should handle not found requests against this API""" kwargs["api"] = self.api - return not_found(*args, **kwargs) + return NotFoundRouter(*args, **kwargs) def static(self, *args, **kwargs): """Define the routes to static files the API should expose""" kwargs["api"] = self.api - return static(*args, **kwargs) + return StaticRouter(*args, **kwargs) def sink(self, *args, **kwargs): """Define URL prefixes/handler matches where everything under the URL prefix should be handled""" kwargs["api"] = self.api - return sink(*args, **kwargs) + return SinkRouter(*args, **kwargs) def exception(self, *args, **kwargs): """Defines how this API should handle the provided exceptions""" kwargs["api"] = self.api - return exception(*args, **kwargs) + return ExceptionRouter(*args, **kwargs) def cli(self, *args, **kwargs): """Defines a CLI function that should be routed by this API""" kwargs["api"] = self.api - return cli(*args, **kwargs) + return CLIRouter(*args, **kwargs) def object(self, *args, **kwargs): """Registers a class based router to this API""" @@ -162,83 +162,83 @@ def get(self, *args, **kwargs): """Builds a new GET HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("GET",) - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def post(self, *args, **kwargs): """Builds a new POST HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("POST",) - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def put(self, *args, **kwargs): """Builds a new PUT HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("PUT",) - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def delete(self, *args, **kwargs): """Builds a new DELETE HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("DELETE",) - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def connect(self, *args, **kwargs): """Builds a new CONNECT HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("CONNECT",) - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def head(self, *args, **kwargs): """Builds a new HEAD HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("HEAD",) - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def options(self, *args, **kwargs): """Builds a new OPTIONS HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("OPTIONS",) - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def patch(self, *args, **kwargs): """Builds a new PATCH HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("PATCH",) - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def trace(self, *args, **kwargs): """Builds a new TRACE HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("TRACE",) - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def get_post(self, *args, **kwargs): """Builds a new GET or POST HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("GET", "POST") - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) def put_post(self, *args, **kwargs): """Builds a new PUT or POST HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("PUT", "POST") - return http(*args, **kwargs) + return URLRouter(*args, **kwargs) for method in HTTP_METHODS: - method_handler = partial(http, accept=(method,)) + method_handler = partial(URLRouter, accept=(method,)) method_handler.__doc__ = "Exposes a Python method externally as an HTTP {0} method".format( method.upper() ) globals()[method.lower()] = method_handler -get_post = partial(http, accept=("GET", "POST")) +get_post = partial(URLRouter, accept=("GET", "POST")) get_post.__doc__ = "Exposes a Python method externally under both the HTTP POST and GET methods" -put_post = partial(http, accept=("PUT", "POST")) +put_post = partial(URLRouter, accept=("PUT", "POST")) put_post.__doc__ = "Exposes a Python method externally under both the HTTP POST and PUT methods" object = Object() # DEPRECATED: for backwords compatibility with hug 1.x.x -call = http +call = URLRouter diff --git a/hug/routing.py b/hug/routing.py index e215f257..4a8af026 100644 --- a/hug/routing.py +++ b/hug/routing.py @@ -221,13 +221,15 @@ def __init__( versions=any, parse_body=False, parameters=None, - defaults={}, + defaults=None, status=None, response_headers=None, private=False, inputs=None, **kwargs ): + if defaults is None: + defaults = {} super().__init__(**kwargs) if versions is not any: self.route["versions"] = ( diff --git a/requirements/build_common.txt b/requirements/build_common.txt index 848e90ac..34c98ea3 100644 --- a/requirements/build_common.txt +++ b/requirements/build_common.txt @@ -8,3 +8,8 @@ wheel==0.29.0 PyJWT==1.4.2 pytest-xdist==1.14.0 numpy==1.15.4 +black==19.3b0 +pep8-naming +flake8-bugbear +vulture +bandit diff --git a/tests/module_fake.py b/tests/module_fake.py index 328feaca..8e5b556a 100644 --- a/tests/module_fake.py +++ b/tests/module_fake.py @@ -60,25 +60,25 @@ def on_startup(api): return -@hug.static() +@hug.StaticRouter() def static(): """for testing""" return ("",) -@hug.sink("/all") +@hug.SinkRouter("/all") def sink(path): """for testing""" return path -@hug.exception(FakeException) +@hug.ExceptionRouter(FakeException) def handle_exception(exception): """Handles the provided exception for testing""" return True -@hug.not_found() +@hug.NotFoundRouter() def not_found_handler(): """for testing""" return True diff --git a/tests/module_fake_http_and_cli.py b/tests/module_fake_http_and_cli.py index 2eda4c37..d361ceae 100644 --- a/tests/module_fake_http_and_cli.py +++ b/tests/module_fake_http_and_cli.py @@ -2,6 +2,6 @@ @hug.get() -@hug.cli() +@hug.CLIRouter() def made_up_go(): return "Going!" diff --git a/tests/test_api.py b/tests/test_api.py index 16dbaa5b..b60137c5 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -81,7 +81,7 @@ def my_route(): def my_second_route(): pass - @hug.cli(api=hug_api) + @hug.CLIRouter(api=hug_api) def my_cli_command(): pass diff --git a/tests/test_async.py b/tests/test_async.py index f25945be..cb81d714 100644 --- a/tests/test_async.py +++ b/tests/test_async.py @@ -45,7 +45,7 @@ def tested_nested_basic_call_async(): async def hello_world(self=None): return await nested_hello_world() - @hug.local() + @hug.LocalRouter() async def nested_hello_world(self=None): return "Hello World!" diff --git a/tests/test_context_factory.py b/tests/test_context_factory.py index f3bc20bd..42ff03dc 100644 --- a/tests/test_context_factory.py +++ b/tests/test_context_factory.py @@ -41,7 +41,7 @@ def test_local_requirement(**kwargs): self.custom_context["launched_requirement"] = True return RequirementFailed() - @hug.local(requires=test_local_requirement) + @hug.LocalRouter(requires=test_local_requirement) def requirement_local_function(): self.custom_context["launched_local_function"] = True @@ -67,7 +67,7 @@ def custom_directive(**kwargs): assert kwargs["context"] == custom_context return "custom" - @hug.local() + @hug.LocalRouter() def directive_local_function(custom: custom_directive): assert custom == "custom" @@ -101,7 +101,7 @@ def custom_number_test(value, context): raise ValueError("not valid number") return value - @hug.local() + @hug.LocalRouter() def validation_local_function(value: custom_number_test): custom_context["launched_local_function"] = value @@ -132,7 +132,7 @@ def check_context(self, data): assert self.context["test"] == "context" self.context["test_number"] += 1 - @hug.local() + @hug.LocalRouter() def validation_local_function() -> UserSchema(): return {"name": "test"} @@ -156,7 +156,7 @@ def delete_context(context, exception=None, errors=None, lacks_requirement=None) assert not lacks_requirement custom_context["launched_delete_context"] = True - @hug.local() + @hug.LocalRouter() def exception_local_function(): custom_context["launched_local_function"] = True raise CustomException() @@ -182,7 +182,7 @@ def delete_context(context, exception=None, errors=None, lacks_requirement=None) assert not lacks_requirement custom_context["launched_delete_context"] = True - @hug.local() + @hug.LocalRouter() def success_local_function(): custom_context["launched_local_function"] = True @@ -215,7 +215,7 @@ def test_requirement(**kwargs): custom_context["launched_requirement"] = True return RequirementFailed() - @hug.cli(requires=test_requirement) + @hug.CLIRouter(requires=test_requirement) def requirement_local_function(): custom_context["launched_local_function"] = True @@ -241,7 +241,7 @@ def custom_directive(**kwargs): assert kwargs["context"] == custom_context return "custom" - @hug.cli() + @hug.CLIRouter() def directive_local_function(custom: custom_directive): assert custom == "custom" @@ -275,7 +275,7 @@ def new_custom_number_test(value, context): raise ValueError("not valid number") return value - @hug.cli() + @hug.CLIRouter() def validation_local_function(value: hug.types.number): custom_context["launched_local_function"] = value return 0 @@ -308,7 +308,7 @@ def check_context(self, data): assert self.context["test"] == "context" self.context["test_number"] += 1 - @hug.cli() + @hug.CLIRouter() def transform_cli_function() -> UserSchema(): custom_context["launched_cli_function"] = True return {"name": "test"} @@ -335,7 +335,7 @@ def delete_context(context, exception=None, errors=None, lacks_requirement=None) assert not lacks_requirement custom_context["launched_delete_context"] = True - @hug.cli() + @hug.CLIRouter() def exception_local_function(): custom_context["launched_local_function"] = True raise CustomException() @@ -360,7 +360,7 @@ def delete_context(context, exception=None, errors=None, lacks_requirement=None) assert not lacks_requirement custom_context["launched_delete_context"] = True - @hug.cli() + @hug.CLIRouter() def success_local_function(): custom_context["launched_local_function"] = True diff --git a/tests/test_coroutines.py b/tests/test_coroutines.py index 556f4fea..8ae41e69 100644 --- a/tests/test_coroutines.py +++ b/tests/test_coroutines.py @@ -46,7 +46,7 @@ def test_nested_basic_call_coroutine(): def hello_world(): return getattr(asyncio, "ensure_future")(nested_hello_world()) - @hug.local() + @hug.LocalRouter() @asyncio.coroutine def nested_hello_world(): return "Hello World!" diff --git a/tests/test_decorators.py b/tests/test_decorators.py index e9e310f8..218c2c19 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -349,7 +349,7 @@ def accepts_get_and_post(): def test_not_found(hug_api): """Test to ensure the not_found decorator correctly routes 404s to the correct handler""" - @hug.not_found(api=hug_api) + @hug.NotFoundRouter(api=hug_api) def not_found_handler(): return "Not Found" @@ -357,7 +357,7 @@ def not_found_handler(): assert result.data == "Not Found" assert result.status == falcon.HTTP_NOT_FOUND - @hug.not_found(versions=10, api=hug_api) # noqa + @hug.NotFoundRouter(versions=10, api=hug_api) # noqa def not_found_handler(response): response.status = falcon.HTTP_OK return {"look": "elsewhere"} @@ -450,7 +450,7 @@ def my_api_function(hug_api_version): assert hug.test.get(api, "v3/my_api_function").data == 3 @hug.get(versions=(None, 1)) - @hug.local(version=1) + @hug.LocalRouter(version=1) def call_other_function(hug_current_api): return hug_current_api.my_api_function() @@ -458,7 +458,7 @@ def call_other_function(hug_current_api): assert call_other_function() == 1 @hug.get(versions=1) - @hug.local(version=1) + @hug.LocalRouter(version=1) def one_more_level_of_indirection(hug_current_api): return hug_current_api.call_other_function() @@ -771,7 +771,7 @@ def test_output_format(hug_api): def augmented(data): return hug.output_format.json(["Augmented", data]) - @hug.cli() + @hug.CLIRouter() @hug.get(suffixes=(".js", "/js"), prefixes="/text") def hello(): return "world" @@ -786,7 +786,7 @@ def hello(): def augmented(data): return hug.output_format.json(["Augmented", data]) - @hug.cli(api=hug_api) + @hug.CLIRouter(api=hug_api) def hello(): return "world" @@ -796,7 +796,7 @@ def hello(): def augmented(data): return hug.output_format.json(["Augmented2", data]) - @hug.cli(api=api) + @hug.CLIRouter(api=api) def hello(): return "world" @@ -950,7 +950,7 @@ def test_extending_api_with_exception_handler(): from tests.module_fake_simple import FakeSimpleException - @hug.exception(FakeSimpleException) + @hug.ExceptionRouter(FakeSimpleException) def handle_exception(exception): return "it works!" @@ -1068,7 +1068,7 @@ def extend_with(): def test_cli(): """Test to ensure the CLI wrapper works as intended""" - @hug.cli("command", "1.0.0", output=str) + @hug.CLIRouter("command", "1.0.0", output=str) def cli_command(name: str, value: int): return (name, value) @@ -1082,7 +1082,7 @@ def test_cli_requires(): def requires_fail(**kwargs): return {"requirements": "not met"} - @hug.cli(output=str, requires=requires_fail) + @hug.CLIRouter(output=str, requires=requires_fail) def cli_command(name: str, value: int): return (name, value) @@ -1097,7 +1097,7 @@ def contains_either(fields): if not fields.get("name", "") and not fields.get("value", 0): return {"name": "must be defined", "value": "must be defined"} - @hug.cli(output=str, validate=contains_either) + @hug.CLIRouter(output=str, validate=contains_either) def cli_command(name: str = "", value: int = 0): return (name, value) @@ -1109,7 +1109,7 @@ def cli_command(name: str = "", value: int = 0): def test_cli_with_defaults(): """Test to ensure CLIs work correctly with default values""" - @hug.cli() + @hug.CLIRouter() def happy(name: str, age: int, birthday: bool = False): if birthday: return "Happy {age} birthday {name}!".format(**locals()) @@ -1125,7 +1125,7 @@ def happy(name: str, age: int, birthday: bool = False): def test_cli_with_hug_types(): """Test to ensure CLIs work as expected when using hug types""" - @hug.cli() + @hug.CLIRouter() def happy(name: hug.types.text, age: hug.types.number, birthday: hug.types.boolean = False): if birthday: return "Happy {age} birthday {name}!".format(**locals()) @@ -1137,7 +1137,7 @@ def happy(name: hug.types.text, age: hug.types.number, birthday: hug.types.boole assert hug.test.cli(happy, "Bob", 5) == "Bob is 5 years old" assert hug.test.cli(happy, "Bob", 5, birthday=True) == "Happy 5 birthday Bob!" - @hug.cli() + @hug.CLIRouter() def succeed(success: hug.types.smart_boolean = False): if success: return "Yes!" @@ -1148,7 +1148,7 @@ def succeed(success: hug.types.smart_boolean = False): assert hug.test.cli(succeed, success=True) == "Yes!" assert "succeed" in str(__hug__.cli) - @hug.cli() + @hug.CLIRouter() def succeed(success: hug.types.smart_boolean = True): if success: return "Yes!" @@ -1158,21 +1158,21 @@ def succeed(success: hug.types.smart_boolean = True): assert hug.test.cli(succeed) == "Yes!" assert hug.test.cli(succeed, success="false") == "No :(" - @hug.cli() + @hug.CLIRouter() def all_the(types: hug.types.multiple = []): return types or ["nothing_here"] assert hug.test.cli(all_the) == ["nothing_here"] assert hug.test.cli(all_the, types=("one", "two", "three")) == ["one", "two", "three"] - @hug.cli() + @hug.CLIRouter() def all_the(types: hug.types.multiple): return types or ["nothing_here"] assert hug.test.cli(all_the) == ["nothing_here"] assert hug.test.cli(all_the, "one", "two", "three") == ["one", "two", "three"] - @hug.cli() + @hug.CLIRouter() def one_of(value: hug.types.one_of(["one", "two"]) = "one"): return value @@ -1183,7 +1183,7 @@ def one_of(value: hug.types.one_of(["one", "two"]) = "one"): def test_cli_with_conflicting_short_options(): """Test to ensure that it's possible to expose a CLI with the same first few letters in option""" - @hug.cli() + @hug.CLIRouter() def test(abe1="Value", abe2="Value2", helper=None): return (abe1, abe2) @@ -1196,8 +1196,8 @@ def test(abe1="Value", abe2="Value2", helper=None): def test_cli_with_directives(): """Test to ensure it's possible to use directives with hug CLIs""" - @hug.cli() - @hug.local() + @hug.CLIRouter() + @hug.LocalRouter() def test(hug_timer): return float(hug_timer) @@ -1212,8 +1212,8 @@ class ClassDirective(object): def __init__(self, *args, **kwargs): self.test = 1 - @hug.cli() - @hug.local(skip_directives=False) + @hug.CLIRouter() + @hug.LocalRouter(skip_directives=False) def test(class_directive: ClassDirective): return class_directive.test @@ -1233,8 +1233,8 @@ def cleanup(self, exception): self.test_object.is_cleanup_launched = True self.test_object.last_exception = exception - @hug.cli() - @hug.local(skip_directives=False) + @hug.CLIRouter() + @hug.LocalRouter(skip_directives=False) def test2(class_directive: ClassDirectiveWithCleanUp): return class_directive.test_object.is_cleanup_launched @@ -1247,8 +1247,8 @@ def test2(class_directive: ClassDirectiveWithCleanUp): assert TestObject.is_cleanup_launched assert TestObject.last_exception is None - @hug.cli() - @hug.local(skip_directives=False) + @hug.CLIRouter() + @hug.LocalRouter(skip_directives=False) def test_with_attribute_error(class_directive: ClassDirectiveWithCleanUp): raise class_directive.test_object2 @@ -1269,8 +1269,8 @@ def test_with_attribute_error(class_directive: ClassDirectiveWithCleanUp): def test_cli_with_named_directives(): """Test to ensure you can pass named directives into the cli""" - @hug.cli() - @hug.local() + @hug.CLIRouter() + @hug.LocalRouter() def test(timer: hug.directives.Timer): return float(timer) @@ -1282,14 +1282,14 @@ def test(timer: hug.directives.Timer): def test_cli_with_output_transform(): """Test to ensure it's possible to use output transforms with hug CLIs""" - @hug.cli() + @hug.CLIRouter() def test() -> int: return "5" assert isinstance(test(), str) assert isinstance(hug.test.cli(test), int) - @hug.cli(transform=int) + @hug.CLIRouter(transform=int) def test(): return "5" @@ -1300,7 +1300,7 @@ def test(): def test_cli_with_short_short_options(): """Test to ensure that it's possible to expose a CLI with 2 very short and similar options""" - @hug.cli() + @hug.CLIRouter() def test(a1="Value", a2="Value2"): return (a1, a2) @@ -1313,7 +1313,7 @@ def test(a1="Value", a2="Value2"): def test_cli_file_return(): """Test to ensure that its possible to return a file stream from a CLI""" - @hug.cli() + @hug.CLIRouter() def test(): return open(os.path.join(BASE_DIRECTORY, "README.md"), "rb") @@ -1323,7 +1323,7 @@ def test(): def test_local_type_annotation(): """Test to ensure local type annotation works as expected""" - @hug.local(raise_on_invalid=True) + @hug.LocalRouter(raise_on_invalid=True) def test(number: int): return number @@ -1331,13 +1331,13 @@ def test(number: int): with pytest.raises(Exception): test("h") - @hug.local(raise_on_invalid=False) + @hug.LocalRouter(raise_on_invalid=False) def test(number: int): return number assert test("h")["errors"] - @hug.local(raise_on_invalid=False, validate=False) + @hug.LocalRouter(raise_on_invalid=False, validate=False) def test(number: int): return number @@ -1347,7 +1347,7 @@ def test(number: int): def test_local_transform(): """Test to ensure local type annotation works as expected""" - @hug.local(transform=str) + @hug.LocalRouter(transform=str) def test(number: int): return number @@ -1357,7 +1357,7 @@ def test(number: int): def test_local_on_invalid(): """Test to ensure local type annotation works as expected""" - @hug.local(on_invalid=str) + @hug.LocalRouter(on_invalid=str) def test(number: int): return number @@ -1371,7 +1371,7 @@ def test_local_requires(): def requirement(**kwargs): return global_state and "Unauthorized" - @hug.local(requires=requirement) + @hug.LocalRouter(requires=requirement) def hello(): return "Hi!" @@ -1383,7 +1383,7 @@ def hello(): def test_static_file_support(): """Test to ensure static file routing works as expected""" - @hug.static("/static") + @hug.StaticRouter("/static") def my_static_dirs(): return (BASE_DIRECTORY,) @@ -1395,7 +1395,7 @@ def my_static_dirs(): def test_static_jailed(): """Test to ensure we can't serve from outside static dir""" - @hug.static("/static") + @hug.StaticRouter("/static") def my_static_dirs(): return ["tests"] @@ -1406,7 +1406,7 @@ def my_static_dirs(): def test_sink_support(): """Test to ensure sink URL routers work as expected""" - @hug.sink("/all") + @hug.SinkRouter("/all") def my_sink(request): return request.path.replace("/all", "") @@ -1429,7 +1429,7 @@ def extend_with(): def test_cli_with_string_annotation(): """Test to ensure CLI's work correctly with string annotations""" - @hug.cli() + @hug.CLIRouter() def test(value_1: "The first value", value_2: "The second value" = None): return True @@ -1439,7 +1439,7 @@ def test(value_1: "The first value", value_2: "The second value" = None): def test_cli_with_args(): """Test to ensure CLI's work correctly when taking args""" - @hug.cli() + @hug.CLIRouter() def test(*values): return values @@ -1452,7 +1452,7 @@ def test_cli_using_method(): class API(object): def __init__(self): - hug.cli()(self.hello_world_method) + hug.CLIRouter()(self.hello_world_method) def hello_world_method(self): variable = "Hello World!" @@ -1467,7 +1467,7 @@ def hello_world_method(self): def test_cli_with_nested_variables(): """Test to ensure that a cli containing multiple nested variables works correctly""" - @hug.cli() + @hug.CLIRouter() def test(value_1=None, value_2=None): return "Hi!" @@ -1477,7 +1477,7 @@ def test(value_1=None, value_2=None): def test_cli_with_exception(): """Test to ensure that a cli with an exception is correctly handled""" - @hug.cli() + @hug.CLIRouter() def test(): raise ValueError() return "Hi!" @@ -1543,7 +1543,7 @@ def do_you_have_request(has_request=False): def test_cli_with_empty_return(): """Test to ensure that if you return None no data will be added to sys.stdout""" - @hug.cli() + @hug.CLIRouter() def test_empty_return(): pass @@ -1553,7 +1553,7 @@ def test_empty_return(): def test_cli_with_multiple_ints(): """Test to ensure multiple ints work with CLI""" - @hug.cli() + @hug.CLIRouter() def test_multiple_cli(ints: hug.types.comma_separated_list): return ints @@ -1566,13 +1566,13 @@ def __call__(self, value): value = super().__call__(value) return [int(number) for number in value] - @hug.cli() + @hug.CLIRouter() def test_multiple_cli(ints: ListOfInts() = []): return ints assert hug.test.cli(test_multiple_cli, ints=["1", "2", "3"]) == [1, 2, 3] - @hug.cli() + @hug.CLIRouter() def test_multiple_cli(ints: hug.types.Multiple[int]() = []): return ints @@ -1643,13 +1643,13 @@ def endpoint(): with pytest.raises(ValueError): hug.test.get(api, "endpoint") - @hug.exception() + @hug.ExceptionRouter() def handle_exception(exception): return "it worked" assert hug.test.get(api, "endpoint").data == "it worked" - @hug.exception(ValueError) # noqa + @hug.ExceptionRouter(ValueError) # noqa def handle_exception(exception): return "more explicit handler also worked" @@ -1679,7 +1679,7 @@ def my_endpoint(one=None, two=None): def test_cli_api(capsys): """Ensure that the overall CLI Interface API works as expected""" - @hug.cli() + @hug.CLIRouter() def my_cli_command(): print("Success!") @@ -1696,7 +1696,7 @@ def my_cli_command(): def test_cli_api_return(): """Ensure returning from a CLI API works as expected""" - @hug.cli() + @hug.CLIRouter() def my_cli_command(): return "Success!" @@ -1838,11 +1838,11 @@ class MyValueError(ValueError): class MySecondValueError(ValueError): pass - @hug.exception(Exception, exclude=MySecondValueError, api=hug_api) + @hug.ExceptionRouter(Exception, exclude=MySecondValueError, api=hug_api) def base_exception_handler(exception): return "base exception handler" - @hug.exception(ValueError, exclude=(MyValueError, MySecondValueError), api=hug_api) + @hug.ExceptionRouter(ValueError, exclude=(MyValueError, MySecondValueError), api=hug_api) def base_exception_handler(exception): return "special exception handler" @@ -1867,7 +1867,7 @@ def full_through_to_raise(): def test_cli_kwargs(hug_api): """Test to ensure cli commands can correctly handle **kwargs""" - @hug.cli(api=hug_api) + @hug.CLIRouter(api=hug_api) def takes_all_the_things(required_argument, named_argument=False, *args, **kwargs): return [required_argument, named_argument, args, kwargs] @@ -1913,8 +1913,8 @@ def output_unicode(): def test_param_rerouting(hug_api): - @hug.local(api=hug_api, map_params={"local_id": "record_id"}) - @hug.cli(api=hug_api, map_params={"cli_id": "record_id"}) + @hug.LocalRouter(api=hug_api, map_params={"local_id": "record_id"}) + @hug.CLIRouter(api=hug_api, map_params={"cli_id": "record_id"}) @hug.get(api=hug_api, map_params={"id": "record_id"}) def pull_record(record_id: hug.types.number): return record_id diff --git a/tests/test_directives.py b/tests/test_directives.py index ca206993..b75d516d 100644 --- a/tests/test_directives.py +++ b/tests/test_directives.py @@ -47,7 +47,7 @@ def test_timer(): assert float(timer) < timer.start @hug.get() - @hug.local() + @hug.LocalRouter() def timer_tester(hug_timer): return hug_timer @@ -146,7 +146,7 @@ def test_session_directive(): def add_session(request, response): request.context["session"] = {"test": "data"} - @hug.local() + @hug.LocalRouter() @hug.get() def session_data(hug_session): return hug_session @@ -164,20 +164,20 @@ def test(time: hug.directives.Timer = 3): assert isinstance(test(1), int) - test = hug.local()(test) + test = hug.LocalRouter()(test) assert isinstance(test(), hug.directives.Timer) def test_local_named_directives(): """Ensure that it's possible to attach directives to local function calling""" - @hug.local() + @hug.LocalRouter() def test(time: __hug__.directive("timer") = 3): return time assert isinstance(test(), hug.directives.Timer) - @hug.local(directives=False) + @hug.LocalRouter(directives=False) def test(time: __hug__.directive("timer") = 3): return time @@ -188,7 +188,7 @@ def test_named_directives_by_name(): """Ensure that it's possible to attach directives to named parameters using only the name of the directive""" @hug.get() - @hug.local() + @hug.LocalRouter() def test(time: __hug__.directive("timer") = 3): return time diff --git a/tests/test_interface.py b/tests/test_interface.py index 2dae81ad..58cc0409 100644 --- a/tests/test_interface.py +++ b/tests/test_interface.py @@ -24,7 +24,7 @@ import hug -@hug.http(("/namer", "/namer/{name}"), ("GET", "POST"), versions=(None, 2)) +@hug.URLRouter(("/namer", "/namer/{name}"), ("GET", "POST"), versions=(None, 2)) def namer(name=None): return name @@ -68,7 +68,7 @@ class TestLocal(object): def test_local_method(self): class MyObject(object): - @hug.local() + @hug.LocalRouter() def my_method(self, argument_1: hug.types.number): return argument_1 diff --git a/tests/test_test.py b/tests/test_test.py index b07539b4..ab9c3513 100644 --- a/tests/test_test.py +++ b/tests/test_test.py @@ -29,7 +29,7 @@ def test_cli(): """Test to ensure the CLI tester works as intended to allow testing CLI endpoints""" - @hug.cli() + @hug.CLIRouter() def my_cli_function(): return "Hello" diff --git a/tox.ini b/tox.ini index 8b850d5c..f96d1e29 100644 --- a/tox.ini +++ b/tox.ini @@ -10,6 +10,9 @@ deps= whitelist_externals=flake8 commands=flake8 hug py.test --cov-report html --cov hug -n auto tests + black --check --verbose hug + vulture hug --min-confidence 100 + bandit -r hug/ -ll [testenv:pywin] deps =-rrequirements/build_windows.txt From 5d75810b083262c9627e8fb5fae8d5d305a5ec32 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 19:44:09 -0700 Subject: [PATCH 02/16] flake8 made decorators look funny; undo --- examples/cli.py | 2 +- examples/multi_file_cli/api.py | 2 +- examples/multi_file_cli/sub_api.py | 2 +- examples/on_startup.py | 2 +- examples/override_404.py | 2 +- examples/quick_start/first_step_1.py | 2 +- examples/quick_start/first_step_2.py | 2 +- examples/quick_start/first_step_3.py | 4 +- examples/secure_auth_with_db_example.py | 6 +- examples/sink_example.py | 2 +- examples/sqlalchemy_example/demo/app.py | 2 +- examples/static_serve.py | 2 +- examples/write_once.py | 4 +- hug/__init__.py | 14 +-- hug/development_runner.py | 4 +- hug/route.py | 68 +++++++------- tests/module_fake.py | 8 +- tests/module_fake_http_and_cli.py | 2 +- tests/test_api.py | 2 +- tests/test_async.py | 2 +- tests/test_context_factory.py | 24 ++--- tests/test_coroutines.py | 2 +- tests/test_decorators.py | 120 ++++++++++++------------ tests/test_directives.py | 12 +-- tests/test_interface.py | 4 +- tests/test_test.py | 2 +- 26 files changed, 149 insertions(+), 149 deletions(-) diff --git a/examples/cli.py b/examples/cli.py index 5ce1a393..efb6a094 100644 --- a/examples/cli.py +++ b/examples/cli.py @@ -2,7 +2,7 @@ import hug -@hug.CLIRouter(version="1.0.0") +@hug.cli(version="1.0.0") def cli(name: "The name", age: hug.types.number): """Says happy birthday to a user""" return "Happy {age} Birthday {name}!\n".format(**locals()) diff --git a/examples/multi_file_cli/api.py b/examples/multi_file_cli/api.py index 885f7343..f7242804 100644 --- a/examples/multi_file_cli/api.py +++ b/examples/multi_file_cli/api.py @@ -3,7 +3,7 @@ import sub_api -@hug.CLIRouter() +@hug.cli() def echo(text: hug.types.text): return text diff --git a/examples/multi_file_cli/sub_api.py b/examples/multi_file_cli/sub_api.py index f550a14f..20ffa319 100644 --- a/examples/multi_file_cli/sub_api.py +++ b/examples/multi_file_cli/sub_api.py @@ -1,6 +1,6 @@ import hug -@hug.CLIRouter() +@hug.cli() def hello(): return "Hello world" diff --git a/examples/on_startup.py b/examples/on_startup.py index d4ffaa85..c6a59744 100644 --- a/examples/on_startup.py +++ b/examples/on_startup.py @@ -16,7 +16,7 @@ def add_more_data(api): data.append("Even subsequent calls") -@hug.CLIRouter() +@hug.cli() @hug.get() def test(): """Returns all stored data""" diff --git a/examples/override_404.py b/examples/override_404.py index ca3b3d07..261d6f14 100644 --- a/examples/override_404.py +++ b/examples/override_404.py @@ -6,6 +6,6 @@ def hello_world(): return "Hello world!" -@hug.NotFoundRouter() +@hug.not_found() def not_found(): return {"Nothing": "to see"} diff --git a/examples/quick_start/first_step_1.py b/examples/quick_start/first_step_1.py index d28ad11f..971ded8f 100644 --- a/examples/quick_start/first_step_1.py +++ b/examples/quick_start/first_step_1.py @@ -2,7 +2,7 @@ import hug -@hug.LocalRouter() +@hug.local() def happy_birthday(name: hug.types.text, age: hug.types.number, hug_timer=3): """Says happy birthday to a user""" return {"message": "Happy {0} Birthday {1}!".format(age, name), "took": float(hug_timer)} diff --git a/examples/quick_start/first_step_2.py b/examples/quick_start/first_step_2.py index 0907e77d..ee314ae5 100644 --- a/examples/quick_start/first_step_2.py +++ b/examples/quick_start/first_step_2.py @@ -3,7 +3,7 @@ @hug.get(examples="name=Timothy&age=26") -@hug.LocalRouter() +@hug.local() def happy_birthday(name: hug.types.text, age: hug.types.number, hug_timer=3): """Says happy birthday to a user""" return {"message": "Happy {0} Birthday {1}!".format(age, name), "took": float(hug_timer)} diff --git a/examples/quick_start/first_step_3.py b/examples/quick_start/first_step_3.py index b206162d..33a02c92 100644 --- a/examples/quick_start/first_step_3.py +++ b/examples/quick_start/first_step_3.py @@ -2,9 +2,9 @@ import hug -@hug.CLIRouter() +@hug.cli() @hug.get(examples="name=Timothy&age=26") -@hug.LocalRouter() +@hug.local() def happy_birthday(name: hug.types.text, age: hug.types.number, hug_timer=3): """Says happy birthday to a user""" return {"message": "Happy {0} Birthday {1}!".format(age, name), "took": float(hug_timer)} diff --git a/examples/secure_auth_with_db_example.py b/examples/secure_auth_with_db_example.py index 0cb1fb74..e1ce207e 100644 --- a/examples/secure_auth_with_db_example.py +++ b/examples/secure_auth_with_db_example.py @@ -36,7 +36,7 @@ def gen_api_key(username): return hash_password(username, salt) -@hug.CLIRouter() +@hug.cli() def authenticate_user(username, password): """ Authenticate a username and password against our database @@ -57,7 +57,7 @@ def authenticate_user(username, password): return False -@hug.CLIRouter() +@hug.cli() def authenticate_key(api_key): """ Authenticate an API key against our database @@ -79,7 +79,7 @@ def authenticate_key(api_key): basic_authentication = hug.authentication.basic(authenticate_user) -@hug.CLIRouter() +@hug.cli() def add_user(username, password): """ CLI Parameter to add a user to the database diff --git a/examples/sink_example.py b/examples/sink_example.py index 5577e88a..aadd395f 100644 --- a/examples/sink_example.py +++ b/examples/sink_example.py @@ -6,6 +6,6 @@ import hug -@hug.SinkRouter("/all") +@hug.sink("/all") def my_sink(request): return request.path.replace("/all", "") diff --git a/examples/sqlalchemy_example/demo/app.py b/examples/sqlalchemy_example/demo/app.py index 1118b1f5..748ca17d 100644 --- a/examples/sqlalchemy_example/demo/app.py +++ b/examples/sqlalchemy_example/demo/app.py @@ -17,7 +17,7 @@ def delete_context(context: SqlalchemyContext, exception=None, errors=None, lack context.cleanup(exception) -@hug.LocalRouter(skip_directives=False) +@hug.local(skip_directives=False) def initialize(db: SqlalchemySession): admin = TestUser(username="admin", password="admin") db.add(admin) diff --git a/examples/static_serve.py b/examples/static_serve.py index dc798c0c..eac7019a 100644 --- a/examples/static_serve.py +++ b/examples/static_serve.py @@ -52,7 +52,7 @@ def setup(api=None): fo.write(image) -@hug.StaticRouter("/static") +@hug.static("/static") def my_static_dirs(): """Returns static directory names to be served.""" global tmp_dir_object diff --git a/examples/write_once.py b/examples/write_once.py index 0db9180c..b61ee09a 100644 --- a/examples/write_once.py +++ b/examples/write_once.py @@ -3,8 +3,8 @@ import requests -@hug.LocalRouter() -@hug.CLIRouter() +@hug.local() +@hug.cli() @hug.get() def top_post(section: hug.types.one_of(("news", "newest", "show")) = "news"): """Returns the top post from the provided section""" diff --git a/hug/__init__.py b/hug/__init__.py index a2e98873..e40d8508 100644 --- a/hug/__init__.py +++ b/hug/__init__.py @@ -68,23 +68,23 @@ ) from hug.route import ( call, - CLIRouter, + cli, connect, delete, - ExceptionRouter, + exception, get, get_post, head, - URLRouter, - LocalRouter, - NotFoundRouter, + http, + local, + not_found, object, options, patch, post, put, - SinkRouter, - StaticRouter, + sink, + static, trace, ) from hug.types import create as type diff --git a/hug/development_runner.py b/hug/development_runner.py index c7fa67c1..196f0713 100644 --- a/hug/development_runner.py +++ b/hug/development_runner.py @@ -32,7 +32,7 @@ import _thread as thread from hug._version import current from hug.api import API -from hug.route import CLIRouter +from hug.route import cli from hug.types import boolean, number INIT_MODULES = list(sys.modules.keys()) @@ -42,7 +42,7 @@ 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) -@CLIRouter(version=current) +@cli(version=current) def hug( file: "A Python file that contains a Hug API" = None, module: "A Python module that contains a Hug API" = None, diff --git a/hug/route.py b/hug/route.py index 1662d209..91eac8a2 100644 --- a/hug/route.py +++ b/hug/route.py @@ -27,16 +27,16 @@ from falcon import HTTP_METHODS import hug.api -from hug.routing import CLIRouter as CLIRouter -from hug.routing import ExceptionRouter as ExceptionRouter -from hug.routing import LocalRouter as LocalRouter -from hug.routing import NotFoundRouter as NotFoundRouter -from hug.routing import SinkRouter as SinkRouter -from hug.routing import StaticRouter as StaticRouter -from hug.routing import URLRouter as URLRouter +from hug.routing import CLIRouter as cli +from hug.routing import ExceptionRouter as exception +from hug.routing import LocalRouter as local +from hug.routing import NotFoundRouter as not_found +from hug.routing import SinkRouter as sink +from hug.routing import StaticRouter as static +from hug.routing import URLRouter as http -class Object(URLRouter): +class Object(http): """Defines a router for classes and objects""" def __init__(self, urls=None, accept=HTTP_METHODS, output=None, **kwargs): @@ -61,11 +61,11 @@ def __call__(self, method_or_class=None, **kwargs): http_routes = getattr(argument, "_hug_http_routes", ()) for route in http_routes: - URLRouter(**self.where(**route).route)(argument) + http(**self.where(**route).route)(argument) cli_routes = getattr(argument, "_hug_cli_routes", ()) for route in cli_routes: - CLIRouter(**self.where(**route).route)(argument) + cli(**self.where(**route).route)(argument) return method_or_class @@ -86,14 +86,14 @@ def decorator(class_definition): http_routes = getattr(handler, "_hug_http_routes", ()) if http_routes: for route in http_routes: - URLRouter(**router.accept(method).where(**route).route)(handler) + http(**router.accept(method).where(**route).route)(handler) else: - URLRouter(**router.accept(method).route)(handler) + http(**router.accept(method).route)(handler) cli_routes = getattr(handler, "_hug_cli_routes", ()) if cli_routes: for route in cli_routes: - CLIRouter(**self.where(**route).route)(handler) + cli(**self.where(**route).route)(handler) return class_definition return decorator @@ -119,7 +119,7 @@ def __init__(self, api): def http(self, *args, **kwargs): """Starts the process of building a new HTTP route linked to this API instance""" kwargs["api"] = self.api - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def urls(self, *args, **kwargs): """DEPRECATED: for backwords compatibility with < hug 2.2.0. `API.http` should be used instead. @@ -131,27 +131,27 @@ def urls(self, *args, **kwargs): def not_found(self, *args, **kwargs): """Defines the handler that should handle not found requests against this API""" kwargs["api"] = self.api - return NotFoundRouter(*args, **kwargs) + return not_found(*args, **kwargs) def static(self, *args, **kwargs): """Define the routes to static files the API should expose""" kwargs["api"] = self.api - return StaticRouter(*args, **kwargs) + return static(*args, **kwargs) def sink(self, *args, **kwargs): """Define URL prefixes/handler matches where everything under the URL prefix should be handled""" kwargs["api"] = self.api - return SinkRouter(*args, **kwargs) + return sink(*args, **kwargs) def exception(self, *args, **kwargs): """Defines how this API should handle the provided exceptions""" kwargs["api"] = self.api - return ExceptionRouter(*args, **kwargs) + return exception(*args, **kwargs) def cli(self, *args, **kwargs): """Defines a CLI function that should be routed by this API""" kwargs["api"] = self.api - return CLIRouter(*args, **kwargs) + return cli(*args, **kwargs) def object(self, *args, **kwargs): """Registers a class based router to this API""" @@ -162,83 +162,83 @@ def get(self, *args, **kwargs): """Builds a new GET HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("GET",) - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def post(self, *args, **kwargs): """Builds a new POST HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("POST",) - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def put(self, *args, **kwargs): """Builds a new PUT HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("PUT",) - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def delete(self, *args, **kwargs): """Builds a new DELETE HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("DELETE",) - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def connect(self, *args, **kwargs): """Builds a new CONNECT HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("CONNECT",) - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def head(self, *args, **kwargs): """Builds a new HEAD HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("HEAD",) - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def options(self, *args, **kwargs): """Builds a new OPTIONS HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("OPTIONS",) - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def patch(self, *args, **kwargs): """Builds a new PATCH HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("PATCH",) - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def trace(self, *args, **kwargs): """Builds a new TRACE HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("TRACE",) - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def get_post(self, *args, **kwargs): """Builds a new GET or POST HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("GET", "POST") - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) def put_post(self, *args, **kwargs): """Builds a new PUT or POST HTTP route that is registered to this API""" kwargs["api"] = self.api kwargs["accept"] = ("PUT", "POST") - return URLRouter(*args, **kwargs) + return http(*args, **kwargs) for method in HTTP_METHODS: - method_handler = partial(URLRouter, accept=(method,)) + method_handler = partial(http, accept=(method,)) method_handler.__doc__ = "Exposes a Python method externally as an HTTP {0} method".format( method.upper() ) globals()[method.lower()] = method_handler -get_post = partial(URLRouter, accept=("GET", "POST")) +get_post = partial(http, accept=("GET", "POST")) get_post.__doc__ = "Exposes a Python method externally under both the HTTP POST and GET methods" -put_post = partial(URLRouter, accept=("PUT", "POST")) +put_post = partial(http, accept=("PUT", "POST")) put_post.__doc__ = "Exposes a Python method externally under both the HTTP POST and PUT methods" object = Object() # DEPRECATED: for backwords compatibility with hug 1.x.x -call = URLRouter +call = http diff --git a/tests/module_fake.py b/tests/module_fake.py index 8e5b556a..328feaca 100644 --- a/tests/module_fake.py +++ b/tests/module_fake.py @@ -60,25 +60,25 @@ def on_startup(api): return -@hug.StaticRouter() +@hug.static() def static(): """for testing""" return ("",) -@hug.SinkRouter("/all") +@hug.sink("/all") def sink(path): """for testing""" return path -@hug.ExceptionRouter(FakeException) +@hug.exception(FakeException) def handle_exception(exception): """Handles the provided exception for testing""" return True -@hug.NotFoundRouter() +@hug.not_found() def not_found_handler(): """for testing""" return True diff --git a/tests/module_fake_http_and_cli.py b/tests/module_fake_http_and_cli.py index d361ceae..2eda4c37 100644 --- a/tests/module_fake_http_and_cli.py +++ b/tests/module_fake_http_and_cli.py @@ -2,6 +2,6 @@ @hug.get() -@hug.CLIRouter() +@hug.cli() def made_up_go(): return "Going!" diff --git a/tests/test_api.py b/tests/test_api.py index b60137c5..16dbaa5b 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -81,7 +81,7 @@ def my_route(): def my_second_route(): pass - @hug.CLIRouter(api=hug_api) + @hug.cli(api=hug_api) def my_cli_command(): pass diff --git a/tests/test_async.py b/tests/test_async.py index cb81d714..f25945be 100644 --- a/tests/test_async.py +++ b/tests/test_async.py @@ -45,7 +45,7 @@ def tested_nested_basic_call_async(): async def hello_world(self=None): return await nested_hello_world() - @hug.LocalRouter() + @hug.local() async def nested_hello_world(self=None): return "Hello World!" diff --git a/tests/test_context_factory.py b/tests/test_context_factory.py index 42ff03dc..f3bc20bd 100644 --- a/tests/test_context_factory.py +++ b/tests/test_context_factory.py @@ -41,7 +41,7 @@ def test_local_requirement(**kwargs): self.custom_context["launched_requirement"] = True return RequirementFailed() - @hug.LocalRouter(requires=test_local_requirement) + @hug.local(requires=test_local_requirement) def requirement_local_function(): self.custom_context["launched_local_function"] = True @@ -67,7 +67,7 @@ def custom_directive(**kwargs): assert kwargs["context"] == custom_context return "custom" - @hug.LocalRouter() + @hug.local() def directive_local_function(custom: custom_directive): assert custom == "custom" @@ -101,7 +101,7 @@ def custom_number_test(value, context): raise ValueError("not valid number") return value - @hug.LocalRouter() + @hug.local() def validation_local_function(value: custom_number_test): custom_context["launched_local_function"] = value @@ -132,7 +132,7 @@ def check_context(self, data): assert self.context["test"] == "context" self.context["test_number"] += 1 - @hug.LocalRouter() + @hug.local() def validation_local_function() -> UserSchema(): return {"name": "test"} @@ -156,7 +156,7 @@ def delete_context(context, exception=None, errors=None, lacks_requirement=None) assert not lacks_requirement custom_context["launched_delete_context"] = True - @hug.LocalRouter() + @hug.local() def exception_local_function(): custom_context["launched_local_function"] = True raise CustomException() @@ -182,7 +182,7 @@ def delete_context(context, exception=None, errors=None, lacks_requirement=None) assert not lacks_requirement custom_context["launched_delete_context"] = True - @hug.LocalRouter() + @hug.local() def success_local_function(): custom_context["launched_local_function"] = True @@ -215,7 +215,7 @@ def test_requirement(**kwargs): custom_context["launched_requirement"] = True return RequirementFailed() - @hug.CLIRouter(requires=test_requirement) + @hug.cli(requires=test_requirement) def requirement_local_function(): custom_context["launched_local_function"] = True @@ -241,7 +241,7 @@ def custom_directive(**kwargs): assert kwargs["context"] == custom_context return "custom" - @hug.CLIRouter() + @hug.cli() def directive_local_function(custom: custom_directive): assert custom == "custom" @@ -275,7 +275,7 @@ def new_custom_number_test(value, context): raise ValueError("not valid number") return value - @hug.CLIRouter() + @hug.cli() def validation_local_function(value: hug.types.number): custom_context["launched_local_function"] = value return 0 @@ -308,7 +308,7 @@ def check_context(self, data): assert self.context["test"] == "context" self.context["test_number"] += 1 - @hug.CLIRouter() + @hug.cli() def transform_cli_function() -> UserSchema(): custom_context["launched_cli_function"] = True return {"name": "test"} @@ -335,7 +335,7 @@ def delete_context(context, exception=None, errors=None, lacks_requirement=None) assert not lacks_requirement custom_context["launched_delete_context"] = True - @hug.CLIRouter() + @hug.cli() def exception_local_function(): custom_context["launched_local_function"] = True raise CustomException() @@ -360,7 +360,7 @@ def delete_context(context, exception=None, errors=None, lacks_requirement=None) assert not lacks_requirement custom_context["launched_delete_context"] = True - @hug.CLIRouter() + @hug.cli() def success_local_function(): custom_context["launched_local_function"] = True diff --git a/tests/test_coroutines.py b/tests/test_coroutines.py index 8ae41e69..556f4fea 100644 --- a/tests/test_coroutines.py +++ b/tests/test_coroutines.py @@ -46,7 +46,7 @@ def test_nested_basic_call_coroutine(): def hello_world(): return getattr(asyncio, "ensure_future")(nested_hello_world()) - @hug.LocalRouter() + @hug.local() @asyncio.coroutine def nested_hello_world(): return "Hello World!" diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 218c2c19..e9e310f8 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -349,7 +349,7 @@ def accepts_get_and_post(): def test_not_found(hug_api): """Test to ensure the not_found decorator correctly routes 404s to the correct handler""" - @hug.NotFoundRouter(api=hug_api) + @hug.not_found(api=hug_api) def not_found_handler(): return "Not Found" @@ -357,7 +357,7 @@ def not_found_handler(): assert result.data == "Not Found" assert result.status == falcon.HTTP_NOT_FOUND - @hug.NotFoundRouter(versions=10, api=hug_api) # noqa + @hug.not_found(versions=10, api=hug_api) # noqa def not_found_handler(response): response.status = falcon.HTTP_OK return {"look": "elsewhere"} @@ -450,7 +450,7 @@ def my_api_function(hug_api_version): assert hug.test.get(api, "v3/my_api_function").data == 3 @hug.get(versions=(None, 1)) - @hug.LocalRouter(version=1) + @hug.local(version=1) def call_other_function(hug_current_api): return hug_current_api.my_api_function() @@ -458,7 +458,7 @@ def call_other_function(hug_current_api): assert call_other_function() == 1 @hug.get(versions=1) - @hug.LocalRouter(version=1) + @hug.local(version=1) def one_more_level_of_indirection(hug_current_api): return hug_current_api.call_other_function() @@ -771,7 +771,7 @@ def test_output_format(hug_api): def augmented(data): return hug.output_format.json(["Augmented", data]) - @hug.CLIRouter() + @hug.cli() @hug.get(suffixes=(".js", "/js"), prefixes="/text") def hello(): return "world" @@ -786,7 +786,7 @@ def hello(): def augmented(data): return hug.output_format.json(["Augmented", data]) - @hug.CLIRouter(api=hug_api) + @hug.cli(api=hug_api) def hello(): return "world" @@ -796,7 +796,7 @@ def hello(): def augmented(data): return hug.output_format.json(["Augmented2", data]) - @hug.CLIRouter(api=api) + @hug.cli(api=api) def hello(): return "world" @@ -950,7 +950,7 @@ def test_extending_api_with_exception_handler(): from tests.module_fake_simple import FakeSimpleException - @hug.ExceptionRouter(FakeSimpleException) + @hug.exception(FakeSimpleException) def handle_exception(exception): return "it works!" @@ -1068,7 +1068,7 @@ def extend_with(): def test_cli(): """Test to ensure the CLI wrapper works as intended""" - @hug.CLIRouter("command", "1.0.0", output=str) + @hug.cli("command", "1.0.0", output=str) def cli_command(name: str, value: int): return (name, value) @@ -1082,7 +1082,7 @@ def test_cli_requires(): def requires_fail(**kwargs): return {"requirements": "not met"} - @hug.CLIRouter(output=str, requires=requires_fail) + @hug.cli(output=str, requires=requires_fail) def cli_command(name: str, value: int): return (name, value) @@ -1097,7 +1097,7 @@ def contains_either(fields): if not fields.get("name", "") and not fields.get("value", 0): return {"name": "must be defined", "value": "must be defined"} - @hug.CLIRouter(output=str, validate=contains_either) + @hug.cli(output=str, validate=contains_either) def cli_command(name: str = "", value: int = 0): return (name, value) @@ -1109,7 +1109,7 @@ def cli_command(name: str = "", value: int = 0): def test_cli_with_defaults(): """Test to ensure CLIs work correctly with default values""" - @hug.CLIRouter() + @hug.cli() def happy(name: str, age: int, birthday: bool = False): if birthday: return "Happy {age} birthday {name}!".format(**locals()) @@ -1125,7 +1125,7 @@ def happy(name: str, age: int, birthday: bool = False): def test_cli_with_hug_types(): """Test to ensure CLIs work as expected when using hug types""" - @hug.CLIRouter() + @hug.cli() def happy(name: hug.types.text, age: hug.types.number, birthday: hug.types.boolean = False): if birthday: return "Happy {age} birthday {name}!".format(**locals()) @@ -1137,7 +1137,7 @@ def happy(name: hug.types.text, age: hug.types.number, birthday: hug.types.boole assert hug.test.cli(happy, "Bob", 5) == "Bob is 5 years old" assert hug.test.cli(happy, "Bob", 5, birthday=True) == "Happy 5 birthday Bob!" - @hug.CLIRouter() + @hug.cli() def succeed(success: hug.types.smart_boolean = False): if success: return "Yes!" @@ -1148,7 +1148,7 @@ def succeed(success: hug.types.smart_boolean = False): assert hug.test.cli(succeed, success=True) == "Yes!" assert "succeed" in str(__hug__.cli) - @hug.CLIRouter() + @hug.cli() def succeed(success: hug.types.smart_boolean = True): if success: return "Yes!" @@ -1158,21 +1158,21 @@ def succeed(success: hug.types.smart_boolean = True): assert hug.test.cli(succeed) == "Yes!" assert hug.test.cli(succeed, success="false") == "No :(" - @hug.CLIRouter() + @hug.cli() def all_the(types: hug.types.multiple = []): return types or ["nothing_here"] assert hug.test.cli(all_the) == ["nothing_here"] assert hug.test.cli(all_the, types=("one", "two", "three")) == ["one", "two", "three"] - @hug.CLIRouter() + @hug.cli() def all_the(types: hug.types.multiple): return types or ["nothing_here"] assert hug.test.cli(all_the) == ["nothing_here"] assert hug.test.cli(all_the, "one", "two", "three") == ["one", "two", "three"] - @hug.CLIRouter() + @hug.cli() def one_of(value: hug.types.one_of(["one", "two"]) = "one"): return value @@ -1183,7 +1183,7 @@ def one_of(value: hug.types.one_of(["one", "two"]) = "one"): def test_cli_with_conflicting_short_options(): """Test to ensure that it's possible to expose a CLI with the same first few letters in option""" - @hug.CLIRouter() + @hug.cli() def test(abe1="Value", abe2="Value2", helper=None): return (abe1, abe2) @@ -1196,8 +1196,8 @@ def test(abe1="Value", abe2="Value2", helper=None): def test_cli_with_directives(): """Test to ensure it's possible to use directives with hug CLIs""" - @hug.CLIRouter() - @hug.LocalRouter() + @hug.cli() + @hug.local() def test(hug_timer): return float(hug_timer) @@ -1212,8 +1212,8 @@ class ClassDirective(object): def __init__(self, *args, **kwargs): self.test = 1 - @hug.CLIRouter() - @hug.LocalRouter(skip_directives=False) + @hug.cli() + @hug.local(skip_directives=False) def test(class_directive: ClassDirective): return class_directive.test @@ -1233,8 +1233,8 @@ def cleanup(self, exception): self.test_object.is_cleanup_launched = True self.test_object.last_exception = exception - @hug.CLIRouter() - @hug.LocalRouter(skip_directives=False) + @hug.cli() + @hug.local(skip_directives=False) def test2(class_directive: ClassDirectiveWithCleanUp): return class_directive.test_object.is_cleanup_launched @@ -1247,8 +1247,8 @@ def test2(class_directive: ClassDirectiveWithCleanUp): assert TestObject.is_cleanup_launched assert TestObject.last_exception is None - @hug.CLIRouter() - @hug.LocalRouter(skip_directives=False) + @hug.cli() + @hug.local(skip_directives=False) def test_with_attribute_error(class_directive: ClassDirectiveWithCleanUp): raise class_directive.test_object2 @@ -1269,8 +1269,8 @@ def test_with_attribute_error(class_directive: ClassDirectiveWithCleanUp): def test_cli_with_named_directives(): """Test to ensure you can pass named directives into the cli""" - @hug.CLIRouter() - @hug.LocalRouter() + @hug.cli() + @hug.local() def test(timer: hug.directives.Timer): return float(timer) @@ -1282,14 +1282,14 @@ def test(timer: hug.directives.Timer): def test_cli_with_output_transform(): """Test to ensure it's possible to use output transforms with hug CLIs""" - @hug.CLIRouter() + @hug.cli() def test() -> int: return "5" assert isinstance(test(), str) assert isinstance(hug.test.cli(test), int) - @hug.CLIRouter(transform=int) + @hug.cli(transform=int) def test(): return "5" @@ -1300,7 +1300,7 @@ def test(): def test_cli_with_short_short_options(): """Test to ensure that it's possible to expose a CLI with 2 very short and similar options""" - @hug.CLIRouter() + @hug.cli() def test(a1="Value", a2="Value2"): return (a1, a2) @@ -1313,7 +1313,7 @@ def test(a1="Value", a2="Value2"): def test_cli_file_return(): """Test to ensure that its possible to return a file stream from a CLI""" - @hug.CLIRouter() + @hug.cli() def test(): return open(os.path.join(BASE_DIRECTORY, "README.md"), "rb") @@ -1323,7 +1323,7 @@ def test(): def test_local_type_annotation(): """Test to ensure local type annotation works as expected""" - @hug.LocalRouter(raise_on_invalid=True) + @hug.local(raise_on_invalid=True) def test(number: int): return number @@ -1331,13 +1331,13 @@ def test(number: int): with pytest.raises(Exception): test("h") - @hug.LocalRouter(raise_on_invalid=False) + @hug.local(raise_on_invalid=False) def test(number: int): return number assert test("h")["errors"] - @hug.LocalRouter(raise_on_invalid=False, validate=False) + @hug.local(raise_on_invalid=False, validate=False) def test(number: int): return number @@ -1347,7 +1347,7 @@ def test(number: int): def test_local_transform(): """Test to ensure local type annotation works as expected""" - @hug.LocalRouter(transform=str) + @hug.local(transform=str) def test(number: int): return number @@ -1357,7 +1357,7 @@ def test(number: int): def test_local_on_invalid(): """Test to ensure local type annotation works as expected""" - @hug.LocalRouter(on_invalid=str) + @hug.local(on_invalid=str) def test(number: int): return number @@ -1371,7 +1371,7 @@ def test_local_requires(): def requirement(**kwargs): return global_state and "Unauthorized" - @hug.LocalRouter(requires=requirement) + @hug.local(requires=requirement) def hello(): return "Hi!" @@ -1383,7 +1383,7 @@ def hello(): def test_static_file_support(): """Test to ensure static file routing works as expected""" - @hug.StaticRouter("/static") + @hug.static("/static") def my_static_dirs(): return (BASE_DIRECTORY,) @@ -1395,7 +1395,7 @@ def my_static_dirs(): def test_static_jailed(): """Test to ensure we can't serve from outside static dir""" - @hug.StaticRouter("/static") + @hug.static("/static") def my_static_dirs(): return ["tests"] @@ -1406,7 +1406,7 @@ def my_static_dirs(): def test_sink_support(): """Test to ensure sink URL routers work as expected""" - @hug.SinkRouter("/all") + @hug.sink("/all") def my_sink(request): return request.path.replace("/all", "") @@ -1429,7 +1429,7 @@ def extend_with(): def test_cli_with_string_annotation(): """Test to ensure CLI's work correctly with string annotations""" - @hug.CLIRouter() + @hug.cli() def test(value_1: "The first value", value_2: "The second value" = None): return True @@ -1439,7 +1439,7 @@ def test(value_1: "The first value", value_2: "The second value" = None): def test_cli_with_args(): """Test to ensure CLI's work correctly when taking args""" - @hug.CLIRouter() + @hug.cli() def test(*values): return values @@ -1452,7 +1452,7 @@ def test_cli_using_method(): class API(object): def __init__(self): - hug.CLIRouter()(self.hello_world_method) + hug.cli()(self.hello_world_method) def hello_world_method(self): variable = "Hello World!" @@ -1467,7 +1467,7 @@ def hello_world_method(self): def test_cli_with_nested_variables(): """Test to ensure that a cli containing multiple nested variables works correctly""" - @hug.CLIRouter() + @hug.cli() def test(value_1=None, value_2=None): return "Hi!" @@ -1477,7 +1477,7 @@ def test(value_1=None, value_2=None): def test_cli_with_exception(): """Test to ensure that a cli with an exception is correctly handled""" - @hug.CLIRouter() + @hug.cli() def test(): raise ValueError() return "Hi!" @@ -1543,7 +1543,7 @@ def do_you_have_request(has_request=False): def test_cli_with_empty_return(): """Test to ensure that if you return None no data will be added to sys.stdout""" - @hug.CLIRouter() + @hug.cli() def test_empty_return(): pass @@ -1553,7 +1553,7 @@ def test_empty_return(): def test_cli_with_multiple_ints(): """Test to ensure multiple ints work with CLI""" - @hug.CLIRouter() + @hug.cli() def test_multiple_cli(ints: hug.types.comma_separated_list): return ints @@ -1566,13 +1566,13 @@ def __call__(self, value): value = super().__call__(value) return [int(number) for number in value] - @hug.CLIRouter() + @hug.cli() def test_multiple_cli(ints: ListOfInts() = []): return ints assert hug.test.cli(test_multiple_cli, ints=["1", "2", "3"]) == [1, 2, 3] - @hug.CLIRouter() + @hug.cli() def test_multiple_cli(ints: hug.types.Multiple[int]() = []): return ints @@ -1643,13 +1643,13 @@ def endpoint(): with pytest.raises(ValueError): hug.test.get(api, "endpoint") - @hug.ExceptionRouter() + @hug.exception() def handle_exception(exception): return "it worked" assert hug.test.get(api, "endpoint").data == "it worked" - @hug.ExceptionRouter(ValueError) # noqa + @hug.exception(ValueError) # noqa def handle_exception(exception): return "more explicit handler also worked" @@ -1679,7 +1679,7 @@ def my_endpoint(one=None, two=None): def test_cli_api(capsys): """Ensure that the overall CLI Interface API works as expected""" - @hug.CLIRouter() + @hug.cli() def my_cli_command(): print("Success!") @@ -1696,7 +1696,7 @@ def my_cli_command(): def test_cli_api_return(): """Ensure returning from a CLI API works as expected""" - @hug.CLIRouter() + @hug.cli() def my_cli_command(): return "Success!" @@ -1838,11 +1838,11 @@ class MyValueError(ValueError): class MySecondValueError(ValueError): pass - @hug.ExceptionRouter(Exception, exclude=MySecondValueError, api=hug_api) + @hug.exception(Exception, exclude=MySecondValueError, api=hug_api) def base_exception_handler(exception): return "base exception handler" - @hug.ExceptionRouter(ValueError, exclude=(MyValueError, MySecondValueError), api=hug_api) + @hug.exception(ValueError, exclude=(MyValueError, MySecondValueError), api=hug_api) def base_exception_handler(exception): return "special exception handler" @@ -1867,7 +1867,7 @@ def full_through_to_raise(): def test_cli_kwargs(hug_api): """Test to ensure cli commands can correctly handle **kwargs""" - @hug.CLIRouter(api=hug_api) + @hug.cli(api=hug_api) def takes_all_the_things(required_argument, named_argument=False, *args, **kwargs): return [required_argument, named_argument, args, kwargs] @@ -1913,8 +1913,8 @@ def output_unicode(): def test_param_rerouting(hug_api): - @hug.LocalRouter(api=hug_api, map_params={"local_id": "record_id"}) - @hug.CLIRouter(api=hug_api, map_params={"cli_id": "record_id"}) + @hug.local(api=hug_api, map_params={"local_id": "record_id"}) + @hug.cli(api=hug_api, map_params={"cli_id": "record_id"}) @hug.get(api=hug_api, map_params={"id": "record_id"}) def pull_record(record_id: hug.types.number): return record_id diff --git a/tests/test_directives.py b/tests/test_directives.py index b75d516d..ca206993 100644 --- a/tests/test_directives.py +++ b/tests/test_directives.py @@ -47,7 +47,7 @@ def test_timer(): assert float(timer) < timer.start @hug.get() - @hug.LocalRouter() + @hug.local() def timer_tester(hug_timer): return hug_timer @@ -146,7 +146,7 @@ def test_session_directive(): def add_session(request, response): request.context["session"] = {"test": "data"} - @hug.LocalRouter() + @hug.local() @hug.get() def session_data(hug_session): return hug_session @@ -164,20 +164,20 @@ def test(time: hug.directives.Timer = 3): assert isinstance(test(1), int) - test = hug.LocalRouter()(test) + test = hug.local()(test) assert isinstance(test(), hug.directives.Timer) def test_local_named_directives(): """Ensure that it's possible to attach directives to local function calling""" - @hug.LocalRouter() + @hug.local() def test(time: __hug__.directive("timer") = 3): return time assert isinstance(test(), hug.directives.Timer) - @hug.LocalRouter(directives=False) + @hug.local(directives=False) def test(time: __hug__.directive("timer") = 3): return time @@ -188,7 +188,7 @@ def test_named_directives_by_name(): """Ensure that it's possible to attach directives to named parameters using only the name of the directive""" @hug.get() - @hug.LocalRouter() + @hug.local() def test(time: __hug__.directive("timer") = 3): return time diff --git a/tests/test_interface.py b/tests/test_interface.py index 58cc0409..2dae81ad 100644 --- a/tests/test_interface.py +++ b/tests/test_interface.py @@ -24,7 +24,7 @@ import hug -@hug.URLRouter(("/namer", "/namer/{name}"), ("GET", "POST"), versions=(None, 2)) +@hug.http(("/namer", "/namer/{name}"), ("GET", "POST"), versions=(None, 2)) def namer(name=None): return name @@ -68,7 +68,7 @@ class TestLocal(object): def test_local_method(self): class MyObject(object): - @hug.LocalRouter() + @hug.local() def my_method(self, argument_1: hug.types.number): return argument_1 diff --git a/tests/test_test.py b/tests/test_test.py index ab9c3513..b07539b4 100644 --- a/tests/test_test.py +++ b/tests/test_test.py @@ -29,7 +29,7 @@ def test_cli(): """Test to ensure the CLI tester works as intended to allow testing CLI endpoints""" - @hug.CLIRouter() + @hug.cli() def my_cli_function(): return "Hello" From 37a5761d4edb50b9be13cd7771af7048492a1362 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 19:47:21 -0700 Subject: [PATCH 03/16] add flake8 ignores to api.py --- Pipfile | 11 +++++++++++ hug/route.py | 14 +++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 Pipfile diff --git a/Pipfile b/Pipfile new file mode 100644 index 00000000..b9ba84f6 --- /dev/null +++ b/Pipfile @@ -0,0 +1,11 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] + +[dev-packages] + +[requires] +python_version = "3.7" diff --git a/hug/route.py b/hug/route.py index 91eac8a2..440a534d 100644 --- a/hug/route.py +++ b/hug/route.py @@ -27,13 +27,13 @@ from falcon import HTTP_METHODS import hug.api -from hug.routing import CLIRouter as cli -from hug.routing import ExceptionRouter as exception -from hug.routing import LocalRouter as local -from hug.routing import NotFoundRouter as not_found -from hug.routing import SinkRouter as sink -from hug.routing import StaticRouter as static -from hug.routing import URLRouter as http +from hug.routing import CLIRouter as cli # noqa: N813 +from hug.routing import ExceptionRouter as exception # noqa: N813 +from hug.routing import LocalRouter as local # noqa: N813 +from hug.routing import NotFoundRouter as not_found # noqa: N813 +from hug.routing import SinkRouter as sink # noqa: N813 +from hug.routing import StaticRouter as static # noqa: N813 +from hug.routing import URLRouter as http # noqa: N813 class Object(http): From 4d96af38b1f64147a3f0eb21a1935ed0ece556b1 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 19:57:16 -0700 Subject: [PATCH 04/16] establish py3.7 versioning for style tools --- requirements/build_common.txt | 10 +++++----- tox.ini | 11 +++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/requirements/build_common.txt b/requirements/build_common.txt index 34c98ea3..0a371909 100644 --- a/requirements/build_common.txt +++ b/requirements/build_common.txt @@ -8,8 +8,8 @@ wheel==0.29.0 PyJWT==1.4.2 pytest-xdist==1.14.0 numpy==1.15.4 -black==19.3b0 -pep8-naming -flake8-bugbear -vulture -bandit +black==19.3b0; python_version == 3.7 +pep8-naming==0.8.2; python_version == 3.7 +flake8-bugbear==19.3.0; python_version == 3.7 +vulture==1.0; python_version == 3.7 +bandit==1.6.0; python_version == 3.7 diff --git a/tox.ini b/tox.ini index f96d1e29..21ff8434 100644 --- a/tox.ini +++ b/tox.ini @@ -8,6 +8,17 @@ deps= marshmallow3: marshmallow >=3.0.0rc5 whitelist_externals=flake8 +commands=flake8 hug + py.test --cov-report html --cov hug -n auto tests + +[testenv:py3.7-marshmallow3] +deps= + -rrequirements/build_common.txt + marshmallow2: marshmallow <3.0 + marshmallow3: marshmallow >=3.0.0rc5 + +whitelist_externals=flake8 + commands=flake8 hug py.test --cov-report html --cov hug -n auto tests black --check --verbose hug From 50ddbe6a1c824045801066f6dafe1fca73c72d72 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 20:04:43 -0700 Subject: [PATCH 05/16] fix the enviro label for tox --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 21ff8434..e8888b61 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,7 @@ whitelist_externals=flake8 commands=flake8 hug py.test --cov-report html --cov hug -n auto tests -[testenv:py3.7-marshmallow3] +[testenv:py37-marshmallow3] deps= -rrequirements/build_common.txt marshmallow2: marshmallow <3.0 From aee2d94af216ab5e4859ff9130817017780efe02 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 20:08:05 -0700 Subject: [PATCH 06/16] specify newer pip --- requirements/build_common.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements/build_common.txt b/requirements/build_common.txt index 0a371909..126768e4 100644 --- a/requirements/build_common.txt +++ b/requirements/build_common.txt @@ -1,4 +1,5 @@ -r common.txt +pip=19.1.1 flake8==3.3.0 isort==4.2.5 pytest-cov==2.4.0 From 20f51ff443157b14b6ea6bde8b5d47f7e3afd1c5 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 20:12:31 -0700 Subject: [PATCH 07/16] try to add pip deps to tox --- requirements/build_common.txt | 1 - tox.ini | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements/build_common.txt b/requirements/build_common.txt index 126768e4..0a371909 100644 --- a/requirements/build_common.txt +++ b/requirements/build_common.txt @@ -1,5 +1,4 @@ -r common.txt -pip=19.1.1 flake8==3.3.0 isort==4.2.5 pytest-cov==2.4.0 diff --git a/tox.ini b/tox.ini index e8888b61..c40ce3b4 100644 --- a/tox.ini +++ b/tox.ini @@ -3,6 +3,7 @@ envlist=py{35,36,37,py3}-marshmallow{2,3}, cython-marshmallow{2,3} [testenv] deps= + pip==19.1.1 -rrequirements/build_common.txt marshmallow2: marshmallow <3.0 marshmallow3: marshmallow >=3.0.0rc5 @@ -13,6 +14,7 @@ commands=flake8 hug [testenv:py37-marshmallow3] deps= + pip==19.1.1 -rrequirements/build_common.txt marshmallow2: marshmallow <3.0 marshmallow3: marshmallow >=3.0.0rc5 From 7fc2d934437d4e3b2bda6ed100ad51ce68217101 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 20:19:29 -0700 Subject: [PATCH 08/16] experiment; is equals req syntax ok? --- tox.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/tox.ini b/tox.ini index c40ce3b4..e8888b61 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,6 @@ envlist=py{35,36,37,py3}-marshmallow{2,3}, cython-marshmallow{2,3} [testenv] deps= - pip==19.1.1 -rrequirements/build_common.txt marshmallow2: marshmallow <3.0 marshmallow3: marshmallow >=3.0.0rc5 @@ -14,7 +13,6 @@ commands=flake8 hug [testenv:py37-marshmallow3] deps= - pip==19.1.1 -rrequirements/build_common.txt marshmallow2: marshmallow <3.0 marshmallow3: marshmallow >=3.0.0rc5 From fff12188b39d65e4156504004d8b46a1556bddf2 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 20:23:58 -0700 Subject: [PATCH 09/16] break up style tools into separate requirements --- requirements/build_common.txt | 6 +----- requirements/build_style_tools.txt | 6 ++++++ tox.ini | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 requirements/build_style_tools.txt diff --git a/requirements/build_common.txt b/requirements/build_common.txt index 0a371909..bd32ae27 100644 --- a/requirements/build_common.txt +++ b/requirements/build_common.txt @@ -8,8 +8,4 @@ wheel==0.29.0 PyJWT==1.4.2 pytest-xdist==1.14.0 numpy==1.15.4 -black==19.3b0; python_version == 3.7 -pep8-naming==0.8.2; python_version == 3.7 -flake8-bugbear==19.3.0; python_version == 3.7 -vulture==1.0; python_version == 3.7 -bandit==1.6.0; python_version == 3.7 + diff --git a/requirements/build_style_tools.txt b/requirements/build_style_tools.txt new file mode 100644 index 00000000..a24c2023 --- /dev/null +++ b/requirements/build_style_tools.txt @@ -0,0 +1,6 @@ +-r build_common.txt +black==19.3b0 +pep8-naming==0.8.2 +flake8-bugbear==19.3.0 +vulture==1.0 +bandit==1.6.0 \ No newline at end of file diff --git a/tox.ini b/tox.ini index e8888b61..5e8f14a8 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,7 @@ commands=flake8 hug [testenv:py37-marshmallow3] deps= - -rrequirements/build_common.txt + -rrequirements/build_style_tools.txt marshmallow2: marshmallow <3.0 marshmallow3: marshmallow >=3.0.0rc5 From c9f648a7ca78b7bf04781d0975529b799cb57400 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 23:09:22 -0700 Subject: [PATCH 10/16] fix repeat env in travis + better test reports in travis --- .travis.yml | 18 +++++++++++++++++- tox.ini | 36 +++++++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index e50d3a4a..9fbf9433 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,23 @@ matrix: - os: linux sudo: required python: 3.7 - env: TOXENV=py37-marshmallow2 + env: TOXENV=py37-marshmallow3 + - os: linux + sudo: required + python: 3.7 + env: TOXENV=py37-black + - os: linux + sudo: required + python: 3.7 + env: TOXENV=py37-flake8 + - os: linux + sudo: required + python: 3.7 + env: TOXENV=py37-bandit + - os: linux + sudo: required + python: 3.7 + env: TOXENV=py37-vulture - os: linux sudo: required python: pypy3.5-6.0 diff --git a/tox.ini b/tox.ini index 5e8f14a8..4393037b 100644 --- a/tox.ini +++ b/tox.ini @@ -8,22 +8,40 @@ deps= marshmallow3: marshmallow >=3.0.0rc5 whitelist_externals=flake8 -commands=flake8 hug - py.test --cov-report html --cov hug -n auto tests +commands=py.test --cov-report html --cov hug -n auto tests -[testenv:py37-marshmallow3] +[testenv:py37-black] deps= -rrequirements/build_style_tools.txt - marshmallow2: marshmallow <3.0 - marshmallow3: marshmallow >=3.0.0rc5 + marshmallow >=3.0.0rc5 whitelist_externals=flake8 +commands=black --check --verbose -l 100 hug + +[testenv:py37-vulture] +deps= + -rrequirements/build_style_tools.txt + marshmallow >=3.0.0rc5 + +whitelist_externals=flake8 +commands=vulture hug --min-confidence 100 + +[testenv:py37-flake8] +deps= + -rrequirements/build_style_tools.txt + marshmallow >=3.0.0rc5 + +whitelist_externals=flake8 commands=flake8 hug - py.test --cov-report html --cov hug -n auto tests - black --check --verbose hug - vulture hug --min-confidence 100 - bandit -r hug/ -ll + +[testenv:py37-bandit] +deps= + -rrequirements/build_style_tools.txt + marshmallow >=3.0.0rc5 + +whitelist_externals=flake8 +commands=bandit -r hug/ -ll [testenv:pywin] deps =-rrequirements/build_windows.txt From 0a460bcb955515d9aa2d2a66f654ccc50f3e700b Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 23:11:39 -0700 Subject: [PATCH 11/16] black reformat, not super happy with this one --- hug/api.py | 1 + hug/route.py | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/hug/api.py b/hug/api.py index 3fdfab2b..1bb9f669 100644 --- a/hug/api.py +++ b/hug/api.py @@ -78,6 +78,7 @@ def __init__(self, api): class HTTPInterfaceAPI(InterfaceAPI): """Defines the HTTP interface specific API""" + __slots__ = ( "routes", "versions", diff --git a/hug/route.py b/hug/route.py index 440a534d..56c3b96c 100644 --- a/hug/route.py +++ b/hug/route.py @@ -27,13 +27,13 @@ from falcon import HTTP_METHODS import hug.api -from hug.routing import CLIRouter as cli # noqa: N813 +from hug.routing import CLIRouter as cli # noqa: N813 from hug.routing import ExceptionRouter as exception # noqa: N813 -from hug.routing import LocalRouter as local # noqa: N813 -from hug.routing import NotFoundRouter as not_found # noqa: N813 -from hug.routing import SinkRouter as sink # noqa: N813 -from hug.routing import StaticRouter as static # noqa: N813 -from hug.routing import URLRouter as http # noqa: N813 +from hug.routing import LocalRouter as local # noqa: N813 +from hug.routing import NotFoundRouter as not_found # noqa: N813 +from hug.routing import SinkRouter as sink # noqa: N813 +from hug.routing import StaticRouter as static # noqa: N813 +from hug.routing import URLRouter as http # noqa: N813 class Object(http): From 0c7adea43dadc67fa96926bdcac722579a71c63f Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 23:48:17 -0700 Subject: [PATCH 12/16] apply isort to CI --- hug/__init__.py | 37 ++++++++++++++++++------------------- tests/test_full_request.py | 10 ++++++---- tox.ini | 8 ++++++++ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/hug/__init__.py b/hug/__init__.py index e40d8508..53cdb76d 100644 --- a/hug/__init__.py +++ b/hug/__init__.py @@ -33,23 +33,6 @@ from falcon import * -from hug import ( - authentication, - directives, - exceptions, - format, - input_format, - introspect, - middleware, - output_format, - redirect, - route, - test, - transform, - types, - use, - validate, -) from hug._version import current from hug.api import API from hug.decorators import ( @@ -89,10 +72,26 @@ ) from hug.types import create as type -from hug import development_runner # isort:skip from hug import ( + authentication, # isort:skip - must be imported last for defaults to have access to all modules defaults, -) # isort:skip - must be imported last for defaults to have access to all modules + directives, + exceptions, + format, + input_format, + introspect, + middleware, + output_format, + redirect, + route, + test, + transform, + types, + use, + validate, +) + +from hug import development_runner # isort:skip try: # pragma: no cover - defaulting to uvloop if it is installed import uvloop diff --git a/tests/test_full_request.py b/tests/test_full_request.py index f7f339a8..56866138 100644 --- a/tests/test_full_request.py +++ b/tests/test_full_request.py @@ -39,11 +39,13 @@ def post(body, response): """ -@pytest.mark.skipif(platform.python_implementation() == "PyPy", reason="Can't run hug CLI from travis PyPy") +@pytest.mark.skipif( + platform.python_implementation() == "PyPy", reason="Can't run hug CLI from travis PyPy" +) def test_hug_post(tmp_path): - hug_test_file = (tmp_path / "hug_postable.py") + hug_test_file = tmp_path / "hug_postable.py" hug_test_file.write_text(TEST_HUG_API) - hug_server = Popen(['hug', '-f', str(hug_test_file), '-p', '3000']) + hug_server = Popen(["hug", "-f", str(hug_test_file), "-p", "3000"]) time.sleep(5) - requests.post('http://127.0.0.1:3000/test', {'data': 'here'}) + requests.post("http://127.0.0.1:3000/test", {"data": "here"}) hug_server.kill() diff --git a/tox.ini b/tox.ini index 4393037b..c1857807 100644 --- a/tox.ini +++ b/tox.ini @@ -43,6 +43,14 @@ deps= whitelist_externals=flake8 commands=bandit -r hug/ -ll +[testenv:py37-isort] +deps= + -rrequirements/build_style_tools.txt + marshmallow >=3.0.0rc5 + +whitelist_externals=flake8 +commands=isort -c hug/*py + [testenv:pywin] deps =-rrequirements/build_windows.txt basepython = {env:PYTHON:}\python.exe From b75fa0d6f380f1f4320f54a4c559efc0a1544433 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 23:49:25 -0700 Subject: [PATCH 13/16] one isort run via hug/*py --- hug/__init__.py | 62 +++++++----------------------------------------- hug/interface.py | 10 +------- 2 files changed, 9 insertions(+), 63 deletions(-) diff --git a/hug/__init__.py b/hug/__init__.py index 53cdb76d..e1100697 100644 --- a/hug/__init__.py +++ b/hug/__init__.py @@ -33,64 +33,18 @@ from falcon import * +from hug import authentication # isort:skip - must be imported last for defaults to have access to all modules +from hug import (defaults, directives, exceptions, format, input_format, introspect, middleware, + output_format, redirect, route, test, transform, types, use, validate) from hug._version import current from hug.api import API -from hug.decorators import ( - context_factory, - default_input_format, - default_output_format, - delete_context, - directive, - extend_api, - middleware_class, - reqresp_middleware, - request_middleware, - response_middleware, - startup, - wraps, -) -from hug.route import ( - call, - cli, - connect, - delete, - exception, - get, - get_post, - head, - http, - local, - not_found, - object, - options, - patch, - post, - put, - sink, - static, - trace, -) +from hug.decorators import (context_factory, default_input_format, default_output_format, + delete_context, directive, extend_api, middleware_class, reqresp_middleware, + request_middleware, response_middleware, startup, wraps) +from hug.route import (call, cli, connect, delete, exception, get, get_post, head, http, local, + not_found, object, options, patch, post, put, sink, static, trace) from hug.types import create as type -from hug import ( - authentication, # isort:skip - must be imported last for defaults to have access to all modules - defaults, - directives, - exceptions, - format, - input_format, - introspect, - middleware, - output_format, - redirect, - route, - test, - transform, - types, - use, - validate, -) - from hug import development_runner # isort:skip try: # pragma: no cover - defaulting to uvloop if it is installed diff --git a/hug/interface.py b/hug/interface.py index 42065774..2b5cda35 100644 --- a/hug/interface.py +++ b/hug/interface.py @@ -38,15 +38,7 @@ from hug import introspect from hug.exceptions import InvalidTypeData from hug.format import parse_content_type -from hug.types import ( - MarshmallowInputSchema, - MarshmallowReturnSchema, - Multiple, - OneOf, - SmartBoolean, - Text, - text, -) +from hug.types import MarshmallowInputSchema, MarshmallowReturnSchema, Multiple, OneOf, SmartBoolean, Text, text def asyncio_call(function, *args, **kwargs): From 3d059796fb10b2ebf68866313dc5d46762039c2e Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 23:50:53 -0700 Subject: [PATCH 14/16] two more isort -c hug/*py runs; second one with a change --- hug/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hug/__init__.py b/hug/__init__.py index e1100697..90f28ea3 100644 --- a/hug/__init__.py +++ b/hug/__init__.py @@ -33,7 +33,6 @@ from falcon import * -from hug import authentication # isort:skip - must be imported last for defaults to have access to all modules from hug import (defaults, directives, exceptions, format, input_format, introspect, middleware, output_format, redirect, route, test, transform, types, use, validate) from hug._version import current @@ -45,6 +44,8 @@ not_found, object, options, patch, post, put, sink, static, trace) from hug.types import create as type +from hug import authentication # isort:skip - must be imported last for defaults to have access to all modules + from hug import development_runner # isort:skip try: # pragma: no cover - defaulting to uvloop if it is installed From 9a365c046917727150e605f8971822258b875667 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Mon, 20 May 2019 23:51:23 -0700 Subject: [PATCH 15/16] black -l 100 run --- hug/__init__.py | 63 ++++++++++++++++++++++++++++++++++++++++++------ hug/interface.py | 10 +++++++- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/hug/__init__.py b/hug/__init__.py index 90f28ea3..9372d155 100644 --- a/hug/__init__.py +++ b/hug/__init__.py @@ -33,18 +33,65 @@ from falcon import * -from hug import (defaults, directives, exceptions, format, input_format, introspect, middleware, - output_format, redirect, route, test, transform, types, use, validate) +from hug import ( + defaults, + directives, + exceptions, + format, + input_format, + introspect, + middleware, + output_format, + redirect, + route, + test, + transform, + types, + use, + validate, +) from hug._version import current from hug.api import API -from hug.decorators import (context_factory, default_input_format, default_output_format, - delete_context, directive, extend_api, middleware_class, reqresp_middleware, - request_middleware, response_middleware, startup, wraps) -from hug.route import (call, cli, connect, delete, exception, get, get_post, head, http, local, - not_found, object, options, patch, post, put, sink, static, trace) +from hug.decorators import ( + context_factory, + default_input_format, + default_output_format, + delete_context, + directive, + extend_api, + middleware_class, + reqresp_middleware, + request_middleware, + response_middleware, + startup, + wraps, +) +from hug.route import ( + call, + cli, + connect, + delete, + exception, + get, + get_post, + head, + http, + local, + not_found, + object, + options, + patch, + post, + put, + sink, + static, + trace, +) from hug.types import create as type -from hug import authentication # isort:skip - must be imported last for defaults to have access to all modules +from hug import ( + authentication, +) # isort:skip - must be imported last for defaults to have access to all modules from hug import development_runner # isort:skip diff --git a/hug/interface.py b/hug/interface.py index 2b5cda35..42065774 100644 --- a/hug/interface.py +++ b/hug/interface.py @@ -38,7 +38,15 @@ from hug import introspect from hug.exceptions import InvalidTypeData from hug.format import parse_content_type -from hug.types import MarshmallowInputSchema, MarshmallowReturnSchema, Multiple, OneOf, SmartBoolean, Text, text +from hug.types import ( + MarshmallowInputSchema, + MarshmallowReturnSchema, + Multiple, + OneOf, + SmartBoolean, + Text, + text, +) def asyncio_call(function, *args, **kwargs): From f2026a43ab8ced80db12a17e2ff91f25dcccd943 Mon Sep 17 00:00:00 2001 From: Jason Tyler Date: Tue, 21 May 2019 00:16:03 -0700 Subject: [PATCH 16/16] black compatible isort config --- .isort.cfg | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .isort.cfg diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 00000000..ba2778dc --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,6 @@ +[settings] +multi_line_output=3 +include_trailing_comma=True +force_grid_wrap=0 +use_parentheses=True +line_length=88