Module hug.decorators
hug/decorators.py
Defines the method decorators at the core of Hug's approach to creating HTTP APIs
- Decorators for exposing python method as HTTP methods (get, post, etc)
- Decorators for setting the default output and input formats used throughout an API using the framework
- Decorator for registering a new directive method
- Decorator for including another API modules handlers into the current one, with opitonal prefix route
Copyright (C) 2016 Timothy Edmund Crosley
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View Source
"""hug/decorators.py Defines the method decorators at the core of Hug's approach to creating HTTP APIs - Decorators for exposing python method as HTTP methods (get, post, etc) - Decorators for setting the default output and input formats used throughout an API using the framework - Decorator for registering a new directive method - Decorator for including another API modules handlers into the current one, with opitonal prefix route Copyright (C) 2016 Timothy Edmund Crosley Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ from __future__ import absolute_import import functools from collections import namedtuple from falcon import HTTP_METHODS import hug.api import hug.defaults import hug.output_format from hug import introspect from hug.format import underscore def default_output_format( content_type="application/json", apply_globally=False, api=None, cli=False, http=True ): """A decorator that allows you to override the default output format for an API""" def decorator(formatter): formatter = hug.output_format.content_type(content_type)(formatter) if apply_globally: if http: hug.defaults.output_format = formatter if cli: hug.defaults.cli_output_format = formatter else: apply_to_api = hug.API(api) if api else hug.api.from_object(formatter) if http: apply_to_api.http.output_format = formatter if cli: apply_to_api.cli.output_format = formatter return formatter return decorator def default_input_format(content_type="application/json", apply_globally=False, api=None): """A decorator that allows you to override the default output format for an API""" def decorator(formatter): formatter = hug.output_format.content_type(content_type)(formatter) if apply_globally: hug.defaults.input_format[content_type] = formatter else: apply_to_api = hug.API(api) if api else hug.api.from_object(formatter) apply_to_api.http.set_input_format(content_type, formatter) return formatter return decorator def directive(apply_globally=False, api=None): """A decorator that registers a single hug directive""" def decorator(directive_method): if apply_globally: hug.defaults.directives[underscore(directive_method.__name__)] = directive_method else: apply_to_api = hug.API(api) if api else hug.api.from_object(directive_method) apply_to_api.add_directive(directive_method) directive_method.directive = True return directive_method return decorator def context_factory(apply_globally=False, api=None): """A decorator that registers a single hug context factory""" def decorator(context_factory_): if apply_globally: hug.defaults.context_factory = context_factory_ else: apply_to_api = hug.API(api) if api else hug.api.from_object(context_factory_) apply_to_api.context_factory = context_factory_ return context_factory_ return decorator def delete_context(apply_globally=False, api=None): """A decorator that registers a single hug delete context function""" def decorator(delete_context_): if apply_globally: hug.defaults.delete_context = delete_context_ else: apply_to_api = hug.API(api) if api else hug.api.from_object(delete_context_) apply_to_api.delete_context = delete_context_ return delete_context_ return decorator def startup(api=None): """Runs the provided function on startup, passing in an instance of the api""" def startup_wrapper(startup_function): apply_to_api = hug.API(api) if api else hug.api.from_object(startup_function) apply_to_api.add_startup_handler(startup_function) return startup_function return startup_wrapper def request_middleware(api=None): """Registers a middleware function that will be called on every request""" def decorator(middleware_method): apply_to_api = hug.API(api) if api else hug.api.from_object(middleware_method) class MiddlewareRouter(object): __slots__ = () def process_request(self, request, response): return middleware_method(request, response) apply_to_api.http.add_middleware(MiddlewareRouter()) return middleware_method return decorator def response_middleware(api=None): """Registers a middleware function that will be called on every response""" def decorator(middleware_method): apply_to_api = hug.API(api) if api else hug.api.from_object(middleware_method) class MiddlewareRouter(object): __slots__ = () def process_response(self, request, response, resource, _req_succeeded): return middleware_method(request, response, resource) apply_to_api.http.add_middleware(MiddlewareRouter()) return middleware_method return decorator def reqresp_middleware(api=None): """Registers a middleware function that will be called on every request and response""" def decorator(middleware_generator): apply_to_api = hug.API(api) if api else hug.api.from_object(middleware_generator) class MiddlewareRouter(object): __slots__ = ("gen",) def process_request(self, request, response): self.gen = middleware_generator(request) return self.gen.__next__() def process_response(self, request, response, resource, _req_succeeded): return self.gen.send((response, resource)) apply_to_api.http.add_middleware(MiddlewareRouter()) return middleware_generator return decorator def middleware_class(api=None): """Registers a middleware class""" def decorator(middleware_class): apply_to_api = hug.API(api) if api else hug.api.from_object(middleware_class) apply_to_api.http.add_middleware(middleware_class()) return middleware_class return decorator def extend_api(route="", api=None, base_url="", **kwargs): """Extends the current api, with handlers from an imported api. Optionally provide a route that prefixes access""" def decorator(extend_with): apply_to_api = hug.API(api) if api else hug.api.from_object(extend_with) for extended_api in extend_with(): apply_to_api.extend(extended_api, route, base_url, **kwargs) return extend_with return decorator def wraps(function): """Enables building decorators around functions used for hug routes without changing their function signature""" def wrap(decorator): decorator = functools.wraps(function)(decorator) if not hasattr(function, "original"): decorator.original = function else: decorator.original = function.original delattr(function, "original") return decorator return wrap def auto_kwargs(function): """Modifies the provided function to support kwargs by only passing along kwargs for parameters it accepts""" supported = introspect.arguments(function) @wraps(function) def call_function(*args, **kwargs): return function(*args, **{key: value for key, value in kwargs.items() if key in supported}) return call_function
Variables
HTTP_METHODS
Functions
auto_kwargs
def auto_kwargs( function )
Modifies the provided function to support kwargs by only passing along kwargs for parameters it accepts
View Source
def auto_kwargs(function): """Modifies the provided function to support kwargs by only passing along kwargs for parameters it accepts""" supported = introspect.arguments(function) @wraps(function) def call_function(*args, **kwargs): return function(*args, **{key: value for key, value in kwargs.items() if key in supported}) return call_function
context_factory
def context_factory( apply_globally=False, api=None )
A decorator that registers a single hug context factory
View Source
def context_factory(apply_globally=False, api=None): """A decorator that registers a single hug context factory""" def decorator(context_factory_): if apply_globally: hug.defaults.context_factory = context_factory_ else: apply_to_api = hug.API(api) if api else hug.api.from_object(context_factory_) apply_to_api.context_factory = context_factory_ return context_factory_ return decorator
default_input_format
def default_input_format( content_type='application/json', apply_globally=False, api=None )
A decorator that allows you to override the default output format for an API
View Source
def default_input_format(content_type="application/json", apply_globally=False, api=None): """A decorator that allows you to override the default output format for an API""" def decorator(formatter): formatter = hug.output_format.content_type(content_type)(formatter) if apply_globally: hug.defaults.input_format[content_type] = formatter else: apply_to_api = hug.API(api) if api else hug.api.from_object(formatter) apply_to_api.http.set_input_format(content_type, formatter) return formatter return decorator
default_output_format
def default_output_format( content_type='application/json', apply_globally=False, api=None, cli=False, http=True )
A decorator that allows you to override the default output format for an API
View Source
def default_output_format( content_type="application/json", apply_globally=False, api=None, cli=False, http=True ): """A decorator that allows you to override the default output format for an API""" def decorator(formatter): formatter = hug.output_format.content_type(content_type)(formatter) if apply_globally: if http: hug.defaults.output_format = formatter if cli: hug.defaults.cli_output_format = formatter else: apply_to_api = hug.API(api) if api else hug.api.from_object(formatter) if http: apply_to_api.http.output_format = formatter if cli: apply_to_api.cli.output_format = formatter return formatter return decorator
delete_context
def delete_context( apply_globally=False, api=None )
A decorator that registers a single hug delete context function
View Source
def delete_context(apply_globally=False, api=None): """A decorator that registers a single hug delete context function""" def decorator(delete_context_): if apply_globally: hug.defaults.delete_context = delete_context_ else: apply_to_api = hug.API(api) if api else hug.api.from_object(delete_context_) apply_to_api.delete_context = delete_context_ return delete_context_ return decorator
directive
def directive( apply_globally=False, api=None )
A decorator that registers a single hug directive
View Source
def directive(apply_globally=False, api=None): """A decorator that registers a single hug directive""" def decorator(directive_method): if apply_globally: hug.defaults.directives[underscore(directive_method.__name__)] = directive_method else: apply_to_api = hug.API(api) if api else hug.api.from_object(directive_method) apply_to_api.add_directive(directive_method) directive_method.directive = True return directive_method return decorator
extend_api
def extend_api( route='', api=None, base_url='', **kwargs )
Extends the current api, with handlers from an imported api. Optionally provide a route that prefixes access
View Source
def extend_api(route="", api=None, base_url="", **kwargs): """Extends the current api, with handlers from an imported api. Optionally provide a route that prefixes access""" def decorator(extend_with): apply_to_api = hug.API(api) if api else hug.api.from_object(extend_with) for extended_api in extend_with(): apply_to_api.extend(extended_api, route, base_url, **kwargs) return extend_with return decorator
middleware_class
def middleware_class( api=None )
Registers a middleware class
View Source
def middleware_class(api=None): """Registers a middleware class""" def decorator(middleware_class): apply_to_api = hug.API(api) if api else hug.api.from_object(middleware_class) apply_to_api.http.add_middleware(middleware_class()) return middleware_class return decorator
reqresp_middleware
def reqresp_middleware( api=None )
Registers a middleware function that will be called on every request and response
View Source
def reqresp_middleware(api=None): """Registers a middleware function that will be called on every request and response""" def decorator(middleware_generator): apply_to_api = hug.API(api) if api else hug.api.from_object(middleware_generator) class MiddlewareRouter(object): __slots__ = ("gen",) def process_request(self, request, response): self.gen = middleware_generator(request) return self.gen.__next__() def process_response(self, request, response, resource, _req_succeeded): return self.gen.send((response, resource)) apply_to_api.http.add_middleware(MiddlewareRouter()) return middleware_generator return decorator
request_middleware
def request_middleware( api=None )
Registers a middleware function that will be called on every request
View Source
def request_middleware(api=None): """Registers a middleware function that will be called on every request""" def decorator(middleware_method): apply_to_api = hug.API(api) if api else hug.api.from_object(middleware_method) class MiddlewareRouter(object): __slots__ = () def process_request(self, request, response): return middleware_method(request, response) apply_to_api.http.add_middleware(MiddlewareRouter()) return middleware_method return decorator
response_middleware
def response_middleware( api=None )
Registers a middleware function that will be called on every response
View Source
def response_middleware(api=None): """Registers a middleware function that will be called on every response""" def decorator(middleware_method): apply_to_api = hug.API(api) if api else hug.api.from_object(middleware_method) class MiddlewareRouter(object): __slots__ = () def process_response(self, request, response, resource, _req_succeeded): return middleware_method(request, response, resource) apply_to_api.http.add_middleware(MiddlewareRouter()) return middleware_method return decorator
startup
def startup( api=None )
Runs the provided function on startup, passing in an instance of the api
View Source
def startup(api=None): """Runs the provided function on startup, passing in an instance of the api""" def startup_wrapper(startup_function): apply_to_api = hug.API(api) if api else hug.api.from_object(startup_function) apply_to_api.add_startup_handler(startup_function) return startup_function return startup_wrapper
wraps
def wraps( function )
Enables building decorators around functions used for hug routes without changing their function signature
View Source
def wraps(function): """Enables building decorators around functions used for hug routes without changing their function signature""" def wrap(decorator): decorator = functools.wraps(function)(decorator) if not hasattr(function, "original"): decorator.original = function else: decorator.original = function.original delattr(function, "original") return decorator return wrap