Пример #1
0
from timeit import timeit
from autoroutes import Routes

PATHS = [
    'user/', 'user/{id}', 'user/{id}/subpath', 'user/{id}/subpath2', 'boat/',
    'boat/{id}', 'boat/{id}/subpath', 'boat/{id}/subpath2', 'horse/',
    'horse/{id}', 'horse/{id}/subpath', 'horse/{id}/subpath2', 'bicycle/',
    'bicycle/{id}', 'bicycle/{id}/subpath2', 'bicycle/{id}/subpath'
]

routes = Routes()
for i, path in enumerate(PATHS):
    routes.add(path, GET=i)

node = routes.match('user/')
print('user/', node)
node = routes.match('horse/22/subpath')
print('horse/22/subpath', node)
node = routes.match('plane/')
print(node)

total = timeit("routes.match('user/')", globals=globals(), number=100000)
print(f'First flat path:\n> {total}')

total = timeit("routes.match('horse/22/subpath')",
               globals=globals(),
               number=100000)
print(f'Middle path with placeholder:\n> {total}')

total = timeit("routes.match('plane/')", globals=globals(), number=100000)
print(f'Not found path:\n> {total}')
Пример #2
0
class Trinket(Application, dict):

    __slots__ = ('hooks', 'routes', 'websockets', 'server')

    handle_request = request_handler

    def __init__(self):
        self.routes = Routes()
        self.websockets = set()
        self.hooks = defaultdict(list)

    async def lookup(self, request: Request):
        payload, params = self.routes.match(request.path)

        if not payload:
            raise HTTPError(HTTPStatus.NOT_FOUND, request.path)

        # Uppercased in order to only consider HTTP verbs.
        handler = payload.get(request.method.upper(), None)
        if handler is None:
            raise HTTPError(HTTPStatus.METHOD_NOT_ALLOWED)

        # We check if the route is for a websocket handler.
        # If it is, we make sure we were asked for an upgrade.
        if payload.get('websocket', False) and not request.upgrade:
            raise HTTPError(HTTPStatus.UPGRADE_REQUIRED,
                            'This is a websocket endpoint, please upgrade.')

        return handler, params

    @handler_events
    async def __call__(self, request: Request):
        handler, params = await self.lookup(request)
        return await handler(request, **params)

    def route(self, path: str, methods: list = None, **extras: dict):
        if methods is None:
            methods = ['GET']

        def wrapper(func):
            payload = {method: func for method in methods}
            payload.update(extras)
            self.routes.add(path, **payload)
            return func

        return wrapper

    def websocket(self, path: str, **extras: dict):
        def wrapper(func):
            @wraps(func)
            async def websocket_handler(request, **params):
                websocket = Websocket(request.socket)
                try:
                    await websocket.upgrade(request)
                    self.websockets.add(websocket)
                    task = await spawn(func, request, websocket, **params)
                    await websocket.flow(task)
                finally:
                    self.websockets.discard(websocket)

            payload = {'GET': websocket_handler, 'websocket': True}
            payload.update(extras)
            self.routes.add(path, **payload)
            return func

        return wrapper

    def listen(self, name: str):
        def wrapper(func):
            self.hooks[name].append(func)

        return wrapper

    async def notify(self, name: str, *args, **kwargs):
        if name in self.hooks:
            for hook in self.hooks[name]:
                result = await hook(*args, **kwargs)
                if result is not None:
                    # Allows to shortcut the chain.
                    return result
        return None

    def start(self, host='127.0.0.1', port=5000, debug=True):
        Server.start(self, host, port, debug)