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)
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')