示例#1
0
 def __init__(self):
     self.__templates_to_cache = []
     self.__jinja = Jinja()
     self.__loop = asyncio.get_event_loop()
     self.__app = web.Application(loop=self.__loop)
     self.__handler = self.__app.make_handler()
     ip = 'localhost' if ACCEPT_ONLY_LOCAL else '0.0.0.0'
     self.__server = self.__loop.create_server(self.__app.make_handler(), ip, PORT)
示例#2
0
class WebApplication:
    def __init__(self):
        self.__templates_to_cache = []
        self.__jinja = Jinja()
        self.__loop = asyncio.get_event_loop()
        self.__app = web.Application(loop=self.__loop)
        self.__handler = self.__app.make_handler()
        ip = 'localhost' if ACCEPT_ONLY_LOCAL else '0.0.0.0'
        self.__server = self.__loop.create_server(self.__app.make_handler(), ip, PORT)

    @staticmethod
    def __import():
        print(">> Importing handlers [PENDING]")
        for root, dirs, files in os.walk('.'):
            handlers = [file for file in files if file.endswith('_handler.py')]
            for handler in handlers:
                path = os.path.join(root, handler)
                print(path)
                spec = importer.spec_from_file_location("#handlers#", path)
                module = importer.module_from_spec(spec)
                spec.loader.exec_module(module)
        print(">> Importing handlers [OK]")

    def __cache_templates(self):
        print(">> Caching templates [PENDING]")
        for template in self.__templates_to_cache:
            self.__jinja.cache(template)
        print(">> Caching templates [OK]")

    def __loop_forever(self):
        self.__loop.run_until_complete(self.__server)
        try:
            self.__loop.run_forever()
        except KeyboardInterrupt:
            pass
        finally:
            self.__server.close()
            self.__loop.run_until_complete(self.__handler.finish_connections(1.0))
            self.__loop.run_until_complete(self.__app.finish())
        self.__loop.close()

    def run(self):
        self.__import()
        self.__cache_templates()
        self.__loop_forever()

    def view(self, url, template):
        def get_view_internal(func):
            async def async_handler(request):
                view_data = await func(request)
                return self.__rendered_template_response(template, view_data)

            decorator_frame = sys._getframe(1)
            path_to_handler_file = decorator_frame.f_locals["__file__"]
            module = decorator_frame.f_locals["__name__"]
            func_name = func.__name__
            if module != "#handlers#":
                return

            self.__app.router.add_route('GET', url, async_handler)
            return async_handler

        self.__templates_to_cache.append(template)
        return get_view_internal

    def form(self, url, form_class):
        assert issubclass(form_class, IndependentForm)

        def form_internal(func):
            async def async_handler(request):
                payload = await request.payload.read()
                query_string = parse_qsl(payload.decode())
                form = form_class(formdata=MultiDict(query_string))
                if form.validate():
                    redirect = await func(request=request, form=form)
                    if redirect is not None:
                        return self.__json_response(dict(
                            type='REDIRECT',
                            data=redirect
                        ))
                return self.__json_response(dict(
                    type='VALIDATION',
                    data=self.__jinja.render(form.template(), dict(form=form))
                ))

            self.__app.router.add_route('POST', url, async_handler)
            print("mapped {0} to url {1}".format(func.__name__, url))
            return async_handler

        return form_internal

    def folder(self, url, local_path, extensions=None):
        if not url.endswith('/'):
            url += '/'
        if not local_path.endswith('/'):
            local_path += '/'

        async def async_handler(request):
            filepath = local_path + request.match_info['path']
            extension = os.path.splitext(filepath)[1]
            if extensions is not None and extension not in extensions:
                return web.HTTPNotFound()
            with open(filepath, 'rb') as file:
                return web.Response(body=file.read(), content_type=MIME_TYPE[extension])

        self.__app.router.add_route('GET', url + "{path:.*}", async_handler)

    def __rendered_template_response(self, template_path, view_data):
        return web.Response(body=self.__jinja.render(template_path, view_data).encode(encoding='utf8'))

    def __json_response(self, json):
        return web.Response(body=dumps(json).encode(encoding='utf8'), content_type='application/json')