/usr/lib/python3/dist-packages/hug/route.py is in python3-hug 2.3.0-1.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | """hug/route.py
Defines user usable routers
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
from functools import partial
from types import FunctionType, MethodType
import hug.api
from falcon import HTTP_METHODS
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(http):
"""Defines a router for classes and objects"""
def __init__(self, urls=None, accept=HTTP_METHODS, output=None, **kwargs):
super().__init__(urls=urls, accept=accept, output=output, **kwargs)
def __call__(self, method_or_class=None, **kwargs):
if not method_or_class and kwargs:
return self.where(**kwargs)
if isinstance(method_or_class, (MethodType, FunctionType)):
routes = getattr(method_or_class, '_hug_http_routes', [])
routes.append(self.route)
method_or_class._hug_http_routes = routes
return method_or_class
instance = method_or_class
if isinstance(method_or_class, type):
instance = method_or_class()
for argument in dir(instance):
argument = getattr(instance, argument, None)
http_routes = getattr(argument, '_hug_http_routes', ())
for route in http_routes:
http(**self.where(**route).route)(argument)
cli_routes = getattr(argument, '_hug_cli_routes', ())
for route in cli_routes:
cli(**self.where(**route).route)(argument)
return method_or_class
def http_methods(self, urls=None, **route_data):
"""Creates routes from a class, where the class method names should line up to HTTP METHOD types"""
def decorator(class_definition):
instance = class_definition
if isinstance(class_definition, type):
instance = class_definition()
router = self.urls(urls if urls else "/{0}".format(instance.__class__.__name__.lower()), **route_data)
for method in HTTP_METHODS:
handler = getattr(instance, method.lower(), None)
if handler:
http_routes = getattr(handler, '_hug_http_routes', ())
if http_routes:
for route in http_routes:
http(**router.accept(method).where(**route).route)(handler)
else:
http(**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)
return class_definition
return decorator
def cli(self, method):
"""Registers a method on an Object as a CLI route"""
routes = getattr(method, '_hug_cli_routes', [])
routes.append(self.route)
method._hug_cli_routes = routes
return method
class API(object):
"""Provides a convient way to route functions to a single API independent of where they live"""
__slots__ = ('api', )
def __init__(self, api):
if type(api) == str:
api = hug.api.API(api)
self.api = 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)
def urls(self, *args, **kwargs):
"""DEPRECATED: for backwords compatibility with < hug 2.2.0. `API.http` should be used instead.
Starts the process of building a new URL HTTP route linked to this API instance
"""
return self.http(*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)
def static(self, *args, **kwargs):
"""Define the routes to static files the API should expose"""
kwargs['api'] = self.api
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 sink(*args, **kwargs)
def exception(self, *args, **kwargs):
"""Defines how this API should handle the provided exceptions"""
kwargs['api'] = self.api
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 cli(*args, **kwargs)
def object(self, *args, **kwargs):
"""Registers a class based router to this API"""
kwargs['api'] = self.api
return Object(*args, **kwargs)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
for method in HTTP_METHODS:
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(http, 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.__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
|