From 98aad41cead0ec1a743e8f6d0d39f1a77aceef92 Mon Sep 17 00:00:00 2001 From: limbocingo Date: Fri, 1 Dec 2023 14:03:21 +0100 Subject: [PATCH] allow debugging for view --- pypulse/Aplication/reader.py | 72 -------- pypulse/Aplication/set_aplication.py | 5 - pypulse/Aplication/vars.py | 1 + pypulse/Socket/handler.py | 65 ++++++++ pypulse/Socket/request_handler.py | 155 ------------------ pypulse/Socket/server.py | 4 +- pypulse/Template/__init__.py | 6 +- pypulse/Template/redirect.py | 19 +++ pypulse/Template/redirect_path.py | 16 -- pypulse/Template/reload.py | 23 +++ .../{render_template.py => render.py} | 8 +- pypulse/Utils/call_ast_exec_module.py | 44 ----- pypulse/Utils/get_apps.py | 33 ++++ pypulse/Utils/routing.py | 35 ++++ pypulse/View/__init__.py | 4 +- pypulse/View/callview.py | 101 ------------ pypulse/View/decorators/__init__.py | 0 pypulse/View/decorators/route.py | 23 +++ pypulse/View/modules.py | 55 +++++++ pypulse/View/setview.py | 54 ------ pypulse/View/types.py | 4 + pypulse/View/view.py | 10 -- pypulse/View/views.py | 57 +++++++ 23 files changed, 327 insertions(+), 467 deletions(-) delete mode 100644 pypulse/Aplication/reader.py create mode 100644 pypulse/Socket/handler.py delete mode 100644 pypulse/Socket/request_handler.py create mode 100644 pypulse/Template/redirect.py delete mode 100644 pypulse/Template/redirect_path.py create mode 100644 pypulse/Template/reload.py rename pypulse/Template/{render_template.py => render.py} (78%) delete mode 100644 pypulse/Utils/call_ast_exec_module.py create mode 100644 pypulse/Utils/get_apps.py create mode 100644 pypulse/Utils/routing.py delete mode 100644 pypulse/View/callview.py create mode 100644 pypulse/View/decorators/__init__.py create mode 100644 pypulse/View/decorators/route.py create mode 100644 pypulse/View/modules.py delete mode 100644 pypulse/View/setview.py create mode 100644 pypulse/View/types.py delete mode 100644 pypulse/View/view.py create mode 100644 pypulse/View/views.py diff --git a/pypulse/Aplication/reader.py b/pypulse/Aplication/reader.py deleted file mode 100644 index 37daf3b..0000000 --- a/pypulse/Aplication/reader.py +++ /dev/null @@ -1,72 +0,0 @@ -import os -import ast - -from .vars import Vars -from pypulse import View - - -def get_imports(node): - imports = [] - for item in node.body: - if isinstance(item, ast.Import): - for alias in item.names: - imports.append((alias.name, alias.asname)) - - elif isinstance(item, ast.ImportFrom): - module = item.module - for alias in item.names: - imports.append((f"{module}.{alias.name}", alias.asname)) - return imports - - -class ReadViews: - @staticmethod - def find_views_ho_are_using_the_decoratos(aplication_dir: str): - - complete_route_path = os.path.join( - Vars.APLICATION_PATH, aplication_dir) - - dirs_module = [] - - for path, subdirs, files in os.walk(complete_route_path): - if '__pycache__' in path: - continue - for name in files: - dirs_module.append(os.path.join(path, name)) - - for file in dirs_module: - with open(file, 'r') as file: - file_contents = file.read() - - # Parse the file's content into an Abstract Syntax Tree (AST) - parsed_ast = ast.parse(file_contents) - - target_decorator = "@view" - - all_imports = get_imports(parsed_ast) - - for node in ast.walk(parsed_ast): - if isinstance(node, ast.FunctionDef): - - for decorator in node.decorator_list: - if isinstance(decorator, ast.Call) and decorator.func.id == target_decorator.lstrip("@"): - current_name = None - current_path_trigger = None - - for keyword in decorator.keywords: - if keyword.arg == "name": - current_name = ast.dump(keyword.value).split( - "value='")[-1].split("'")[0] - elif keyword.arg == "path_trigger": - current_path_trigger = ast.dump( - keyword.value).split("value='")[-1].split("'")[0] - - if current_name is not None and current_path_trigger is not None: - break - - View.SetView( - f'{aplication_dir}___{current_name}', - node, - all_imports, - current_path_trigger - ) diff --git a/pypulse/Aplication/set_aplication.py b/pypulse/Aplication/set_aplication.py index 4b5c270..2e03719 100644 --- a/pypulse/Aplication/set_aplication.py +++ b/pypulse/Aplication/set_aplication.py @@ -1,17 +1,12 @@ from .aplication import Aplication -from .reader import ReadViews -from pypulse.View.view import View class SetAplication: def __init__(self, name: str) -> None: - # finding the views of this aplication self._check_if_aplication_is_already_registered(name) - ReadViews.find_views_ho_are_using_the_decoratos(name) Aplication(name) def _check_if_aplication_is_already_registered(self, name:str): for i in Aplication.instances: if i.name == name: raise ValueError('The Aplication is already registered: {name}') - \ No newline at end of file diff --git a/pypulse/Aplication/vars.py b/pypulse/Aplication/vars.py index ce52386..60225bd 100644 --- a/pypulse/Aplication/vars.py +++ b/pypulse/Aplication/vars.py @@ -1,3 +1,4 @@ class Vars: APLICATION_PATH = None INTERNAL_HTTP_SERVER_PORT = 63333 + VIEWS = [] diff --git a/pypulse/Socket/handler.py b/pypulse/Socket/handler.py new file mode 100644 index 0000000..e2dcbac --- /dev/null +++ b/pypulse/Socket/handler.py @@ -0,0 +1,65 @@ +import http.server +from urllib import parse + +from pypulse.Template import Template +from pypulse.View.views import get + + +class Request(http.server.SimpleHTTPRequestHandler): + raw_request = None + response = None + + def __check_request(self): + self.__request_content() + + view = get(self.path) + if not view: + return False + + self.response = view[0]( + self) if not view[1] else view[0](self, **view[1]) + + if type(self.response).__name__ not in ['Redirect', 'RenderTemplate', 'Reload']: + return False + + return True + + def __request_content(self): + raw_length = self.headers.get('content-length') + if not raw_length: + return + length = int(raw_length) + + self.raw_request = self.rfile.read(length) + + def __return_template(self): + if not self.response: + return + + render, redirect = self.response.render_template(self) + self.end_headers() + if not redirect: + template = ' '.join(render.splitlines()) + + self.wfile.write(template.encode()) + + def __handler(self): + condition = self.__check_request() + + if not condition: + return getattr(http.server.SimpleHTTPRequestHandler, f'do_{self.command}')(self) + + self.__return_template() + + def __init__(self, *args, **kwargs): + super().__init__(*args, directory=Template.STATIC_PATH, **kwargs) + + @property + def parameters(self): + result = {} + for i in parse.parse_qsl(self.raw_request): + result[i[0].decode()] = i[1].decode() + return result + + def do_GET(self): self.__handler() + def do_POST(self): self.__handler() diff --git a/pypulse/Socket/request_handler.py b/pypulse/Socket/request_handler.py deleted file mode 100644 index 5029b0a..0000000 --- a/pypulse/Socket/request_handler.py +++ /dev/null @@ -1,155 +0,0 @@ -import http.server - -from pypulse import View -from pypulse.Template import Template -from pypulse.Utils import execute_ast_view_request -import urllib.parse - -class RequestHandler(http.server.SimpleHTTPRequestHandler): - def __init__(self, *args, **kwargs): - super().__init__(*args, directory=Template.STATIC_PATH, **kwargs) - - def do_GET(self): - current_view = View.CallView(self.path) - if current_view.name is not None: - request = { - 'method': 'GET', - 'headers': { - 'Host': self.headers.get('Host'), - 'Upgrade-Insecure-Requests': self.headers.get('Upgrade-Insecure-Requests'), - 'User-Agent': self.headers.get('User-Agent'), - 'Accept': self.headers.get('Accept'), - 'Accept-Encoding': self.headers.get('Accept-Encoding'), - 'Accept-Language': self.headers.get('Accept-Language') - } - } - - render = execute_ast_view_request( - node_body=current_view.view, request=request, requirement_view=current_view.requirement_view, other_variables=current_view.variables_list) - - if type(render).__name__ == 'Redirect': - render = render.get_render(request) - - template = str.join(" ", render.render_template().splitlines()) - self.send_response(200) - self.send_header('Content-type', 'text/html') - self.end_headers() - self.wfile.write(template.encode()) - else: - super().do_GET() - - def do_POST(self): - content_length = int(self.headers['Content-Length']) - post_body = urllib.parse.parse_qs(self.rfile.read(content_length).decode('utf-8')) - temp_post_body = {} - - for i in post_body: - temp_post_body[i] = post_body[i][0] - - current_view = View.CallView(self.path) - - if current_view.name is not None: - request = { - 'method': 'POST', - 'headers': { - 'Host': self.headers.get('Host'), - 'Upgrade-Insecure-Requests': self.headers.get('Upgrade-Insecure-Requests'), - 'User-Agent': self.headers.get('User-Agent'), - 'Accept': self.headers.get('Accept'), - 'Accept-Encoding': self.headers.get('Accept-Encoding'), - 'Accept-Language': self.headers.get('Accept-Language') - }, - 'body': temp_post_body - } - - render = execute_ast_view_request( - node_body=current_view.view, request=request, requirement_view=current_view.requirement_view) - - if type(render).__name__ == 'Redirect': - render = render.get_render(request) - - template = str.join(" ", render.render_template().splitlines()) - self.send_response(200) - self.send_header('Content-type', 'text/html') - self.end_headers() - self.wfile.write(template.encode()) - else: - super().do_POST() - - def do_PUT(self): - content_length = int(self.headers['Content-Length']) - post_body = self.rfile.read(content_length) - temp_post_body = {} - for i in post_body.decode('utf-8').split('&'): - element = i.split('=') - if len(element) == 2: - temp_post_body[element[0]] = element[1] - - current_view = View.CallView(self.path) - - if current_view.name is not None: - request = { - 'method': 'PUT', - 'headers': { - 'Host': self.headers.get('Host'), - 'Upgrade-Insecure-Requests': self.headers.get('Upgrade-Insecure-Requests'), - 'User-Agent': self.headers.get('User-Agent'), - 'Accept': self.headers.get('Accept'), - 'Accept-Encoding': self.headers.get('Accept-Encoding'), - 'Accept-Language': self.headers.get('Accept-Language') - }, - 'body': temp_post_body - } - - render = execute_ast_view_request( - node_body=current_view.view, request=request, requirement_view=current_view.requirement_view) - - if type(render).__name__ == 'Redirect': - render = render.get_render(request) - - template = str.join(" ", render.render_template().splitlines()) - self.send_response(200) - self.send_header('Content-type', 'text/html') - self.end_headers() - self.wfile.write(template.encode()) - else: - super().do_PUT() - - def do_PATCH(self): - content_length = int(self.headers['Content-Length']) - post_body = self.rfile.read(content_length) - temp_post_body = {} - for i in post_body.decode('utf-8').split('&'): - element = i.split('=') - if len(element) == 2: - temp_post_body[element[0]] = element[1] - - current_view = View.CallView(self.path) - - if current_view.name is not None: - request = { - 'method': 'PATCH', - 'headers': { - 'Host': self.headers.get('Host'), - 'Upgrade-Insecure-Requests': self.headers.get('Upgrade-Insecure-Requests'), - 'User-Agent': self.headers.get('User-Agent'), - 'Accept': self.headers.get('Accept'), - 'Accept-Encoding': self.headers.get('Accept-Encoding'), - 'Accept-Language': self.headers.get('Accept-Language') - }, - 'body': temp_post_body - } - - render = execute_ast_view_request( - node_body=current_view.view, request=request, requirement_view=current_view.requirement_view) - - if type(render).__name__ == 'Redirect': - render = render.get_render(request) - - template = str.join(" ", render.render_template().splitlines()) - self.send_response(200) - self.send_header('Content-type', 'text/html') - self.end_headers() - self.wfile.write(template.encode()) - else: - super().do_PATCH() diff --git a/pypulse/Socket/server.py b/pypulse/Socket/server.py index 55ced99..ec6fc1f 100644 --- a/pypulse/Socket/server.py +++ b/pypulse/Socket/server.py @@ -1,10 +1,10 @@ import socketserver -from .request_handler import RequestHandler +from pypulse.Socket.handler import Request from pypulse.Aplication import Vars httpd = socketserver.TCPServer( - ("", Vars.INTERNAL_HTTP_SERVER_PORT), RequestHandler) + ("", Vars.INTERNAL_HTTP_SERVER_PORT), Request) def run_socket(): diff --git a/pypulse/Template/__init__.py b/pypulse/Template/__init__.py index 4307584..73929e3 100644 --- a/pypulse/Template/__init__.py +++ b/pypulse/Template/__init__.py @@ -1,3 +1,3 @@ -from .render_template import RenderTemplate -from .template import Template -from .redirect_path import Redirect +from pypulse.Template.render import RenderTemplate +from pypulse.Template.redirect import Redirect +from pypulse.Template.reload import Reload diff --git a/pypulse/Template/redirect.py b/pypulse/Template/redirect.py new file mode 100644 index 0000000..0c51b3b --- /dev/null +++ b/pypulse/Template/redirect.py @@ -0,0 +1,19 @@ +from pypulse.Aplication.vars import Vars +from pypulse.View.views import get + + +class Redirect(): + def __init__(self, path: str) -> None: + self.path = path + + def render_template(self, request): + if self.path == request.path or get(request.path) == self.path: + print( + f'You tried to redirect to `{self.path}`, route that you are already in.') + print(f'If you want to reload the current view, use `Reload`.') + exit(1) + + request.send_response(301) + request.send_header( + 'Location', f'http://localhost:{Vars.INTERNAL_HTTP_SERVER_PORT}' + self.path) + return None, True diff --git a/pypulse/Template/redirect_path.py b/pypulse/Template/redirect_path.py deleted file mode 100644 index d93b222..0000000 --- a/pypulse/Template/redirect_path.py +++ /dev/null @@ -1,16 +0,0 @@ -from pypulse.View import CallView -from pypulse.Utils import execute_ast_view_request - - -class Redirect(): - def __init__(self, path: str) -> None: - self.view = CallView(path) - - def get_render(self, request): - render = execute_ast_view_request( - node_body=self.view.view, request=request, requirement_view=self.view.requirement_view) - - if type(render).__name__ == 'Redirect': - raise RecursionError('You cant do a recursive redirect!') - - return render diff --git a/pypulse/Template/reload.py b/pypulse/Template/reload.py new file mode 100644 index 0000000..dcbcf80 --- /dev/null +++ b/pypulse/Template/reload.py @@ -0,0 +1,23 @@ +from pypulse.Aplication.vars import Vars +from pypulse.View.views import get + + +class Reload: + + def __init__(self) -> None: + pass + + def render_template(self, request): + view = get(request.path) + request.command = 'GET' + response = view[0](request) if not view[1] else view[0]( + request, **view[1]) + if type(response).__name__ == 'Reload': + print( + f'Path `{request.path}` returns reload in a loop (infinite recursion).') + exit(1) + + request.send_response(301) + request.send_header( + 'Location', f'http://localhost:{Vars.INTERNAL_HTTP_SERVER_PORT}' + request.path) + return None, True diff --git a/pypulse/Template/render_template.py b/pypulse/Template/render.py similarity index 78% rename from pypulse/Template/render_template.py rename to pypulse/Template/render.py index 23aa579..75eeba6 100644 --- a/pypulse/Template/render_template.py +++ b/pypulse/Template/render.py @@ -10,10 +10,14 @@ def __init__(self, template_route: str, variables_dict: dict = None) -> None: self.envirenemnt = Environment( loader=FileSystemLoader(Template.TEMPLATE_PATH)) - def render_template(self): + def render_template(self, request): + request.send_response(200) + request.send_header('Content-type', 'text/html') + template = self.envirenemnt.get_template(self.template_route) if self.variables_dict is not None: output = template.render(self.variables_dict) else: output = template.render() - return output + + return output, False diff --git a/pypulse/Utils/call_ast_exec_module.py b/pypulse/Utils/call_ast_exec_module.py deleted file mode 100644 index 958fd3d..0000000 --- a/pypulse/Utils/call_ast_exec_module.py +++ /dev/null @@ -1,44 +0,0 @@ -import ast - - -def execute_ast_view_request(request: str, node_body: object, requirement_view: list, other_variables: dict = {}) -> None: - module_body = [] - - for i in requirement_view: - import_q = i[0] - import_as_name = i[1] - - if '.' in import_q: - current_path = import_q.rsplit('.', 1) - import_lib = ast.ImportFrom( - module=current_path[0], - names=[ast.alias(name=current_path[1], asname=import_as_name)], - level=0 - ) - else: - import_lib = ast.Import( - names=[ast.alias(name=import_q, asname=import_as_name)]) - - import_lib.lineno = 1 - import_lib.col_offset = 0 - module_body.append(import_lib) - - module_body.append(node_body) - - object_view = ast.Module( - body=module_body, type_ignores=[]) - - namespace = {} - - object_view = exec( - compile(object_view, f'{node_body.name}_view', 'exec'), - namespace - ) - - variables = { - 'request': request - } - - variables.update(other_variables) - - return namespace[node_body.name](**variables) diff --git a/pypulse/Utils/get_apps.py b/pypulse/Utils/get_apps.py new file mode 100644 index 0000000..d97ecf9 --- /dev/null +++ b/pypulse/Utils/get_apps.py @@ -0,0 +1,33 @@ +import os + +from pypulse.Aplication.aplication import Aplication +from pypulse.Aplication.vars import Vars + + +def get_folders(path: str): + dir = os.listdir(path) + result = [] + + for i in dir: + if not os.path.isdir(path + "\\" + i): + continue + + result.append(i) + + return result + + +def applications(): + folder = get_folders(Vars.APLICATION_PATH) + apps = [] + + for i in folder: + if not i: + continue + + if i not in [j.name for j in Aplication.instances]: + continue + + apps.append(i) + + return apps diff --git a/pypulse/Utils/routing.py b/pypulse/Utils/routing.py new file mode 100644 index 0000000..e06011c --- /dev/null +++ b/pypulse/Utils/routing.py @@ -0,0 +1,35 @@ +def repl(string: str, + character: str, + index: int, + condition: bool = None) -> str: + + if condition != None and not condition: + return string + + string = list(string) + string[index] = character + string = ''.join(string) + + return string + + +def variable_info(text: str): + text = repl(text, '', 0) + text = repl(text, '', -1) + + type, name = text.split(':') + return type, name + + +def is_variable(text: str): + if not text.startswith('<') or not text.endswith('>'): + return False + + text = repl(text, '', 0) + text = repl(text, '', -1) + + text = text.split(':') + if len(text) != 2: + raise ValueError('You tried to add more than one argument or none.') + + return True diff --git a/pypulse/View/__init__.py b/pypulse/View/__init__.py index 1d1944e..5f22290 100644 --- a/pypulse/View/__init__.py +++ b/pypulse/View/__init__.py @@ -1,3 +1 @@ -from .setview import view -from .setview import SetView -from .callview import CallView \ No newline at end of file +from pypulse.View.decorators.route import view \ No newline at end of file diff --git a/pypulse/View/callview.py b/pypulse/View/callview.py deleted file mode 100644 index bf4cc18..0000000 --- a/pypulse/View/callview.py +++ /dev/null @@ -1,101 +0,0 @@ -from .view import View - - -class CallView: - def __init__(self, path_to_find: str) -> None: - self.name = None - self.view = None - self.requirement_view = None - self.path_trigger = None - self.variables_list = {} - - path_to_find = path_to_find.split('/') - - for i in View.instances: - path = i.path_trigger.split('/') - - if len(path) != len(path_to_find): - continue - - path_contain_variable = False - index = [] - variables_for_index = {} - - for j in path: - if len(j) > 0: - path_variable_parameters = self.find_if_variable_in_path(j) - if path_variable_parameters[0] != False: - path_contain_variable = True - - variables_for_index[j] = ( - path_variable_parameters[2], path_variable_parameters[1]) - index.append(j) - - # infind the variable and his context call - if path_contain_variable: - # this is the part wee dont check at moment - view_finded = True - - for path_view in range(len(path)): - # excluding the variables - element_finded = False - for elements_in_path in index: - if path.index(elements_in_path) == path_view: - element_finded = True - break - - if element_finded: - continue - - if path[path_view] != path_to_find[path_view]: - view_finded = False - - if view_finded: - self.name = i.name - self.view = i.view - self.requirement_view = i.requirement_view - self.path_trigger = i.path_trigger - - for current_index_path_variable in index: - self.variables_list[variables_for_index[current_index_path_variable][0]] = self.parse_varible( - path_to_find[path.index(current_index_path_variable)], variables_for_index[current_index_path_variable][1]) - - break - - if path_contain_variable == False: - if path == path_to_find: - self.name = i.name - self.view = i.view - self.requirement_view = i.requirement_view - self.path_trigger = i.path_trigger - break - - def find_if_variable_in_path(self, current_path_element: str): - # works whit: int, str, float - - methods_allowed = ['str', 'int', 'float'] - - if '<' != current_path_element[0] and '>' != current_path_element[-1]: - return (False, ) - - if ':' not in current_path_element: - raise ValueError( - f'The parameter you are setting in the path {current_path_element} are incorrect formated') - - type_of_var, var_name = current_path_element[1:-1].split(':') - - if type_of_var.lower() not in methods_allowed: - raise TypeError( - f'The type you are passing in the path {current_path_element} are not in the list of allowed var types {methods_allowed}') - - return (True, type_of_var, var_name) - - def parse_varible(self, variable: str, type_var: str): - if type_var.lower() == 'str': - return str(variable) - - if type_var.lower() == 'int': - return int(variable) - - if type_var.lower() == 'float': - return float(variable) diff --git a/pypulse/View/decorators/__init__.py b/pypulse/View/decorators/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pypulse/View/decorators/route.py b/pypulse/View/decorators/route.py new file mode 100644 index 0000000..ba0cc2d --- /dev/null +++ b/pypulse/View/decorators/route.py @@ -0,0 +1,23 @@ +import random +import string + +from pypulse.Aplication.vars import Vars + + +def view(name: str, path_trigger: str): + def inner(function): + def wrapper(*args, **kwargs): + return function(*args, **kwargs) + + token = ''.join(random.choices( + string.ascii_lowercase + string.digits, k=8)) + Vars.VIEWS.append(token) + + wrapper.__name__ = token + wrapper.route = path_trigger + wrapper.name = name + + wrapper.redirect = False + + return wrapper + return inner diff --git a/pypulse/View/modules.py b/pypulse/View/modules.py new file mode 100644 index 0000000..5b47209 --- /dev/null +++ b/pypulse/View/modules.py @@ -0,0 +1,55 @@ +import importlib +import inspect +import os + +from pypulse.Aplication.vars import Vars + + +def filter_files(extension: str, files: str): + filtered = [] + for file in files: + if not file.endswith('.' + extension): + continue + filtered.append(file) + + return filtered + + +def modules(folder: str) -> list: + files: list[str] = [f'{folder}' + os.sep + file + # add as suffix the folder + for file in filter_files('py', os.listdir(folder))] + + modules: list = [] + for file in files: + separate_folder = file.split('\\') + separate_folder[-1] = separate_folder[-1].rsplit('.', 1)[0] + name = '.'.join(separate_folder) + + spec = importlib.util.spec_from_file_location(name, file) + view_module = importlib.util.module_from_spec(spec) + + spec.loader.exec_module(view_module) + modules.append(view_module) + + return modules + + +def filter_views(module) -> list: + attributes = dir(module) + views = [] + for attr_name in attributes: + attr = getattr(module, attr_name) + + if not inspect.isfunction(attr): + continue + + if attr.__name__ in globals(): + continue + + if attr.__name__ not in Vars.VIEWS: + continue + + views.append(attr) + + return views diff --git a/pypulse/View/setview.py b/pypulse/View/setview.py deleted file mode 100644 index 11fdca2..0000000 --- a/pypulse/View/setview.py +++ /dev/null @@ -1,54 +0,0 @@ -from .view import View - - -class SetView: - def __init__(self, name: str, view: object, requirement_view: list, path_trigger: str) -> None: - self._validate_new_view_consistance(name, path_trigger) - View(name, view, requirement_view, path_trigger) - - def _validate_new_view_consistance(self, name, path_trigger): - if len(View.instances) == 0: - return - - if name in [i.name for i in View.instances]: - raise KeyError(f'The view with the name {name} already exists') - - if path_trigger in [i.path_trigger for i in View.instances]: - raise KeyError( - f'The view with the path_trigger {path_trigger} already exists') - - for i in View.instances: - current_path_instance_new = [] - current_paths_in_views_new = [] - - current_path_instance = path_trigger.split('/') - current_paths_in_views = i.path_trigger.split('/') - - # removing the variables and see if match - - for j in current_path_instance: - if len(j) == 0: - current_path_instance_new.append(j) - continue - if j[0] != '<' and j[-1] != '>': - current_path_instance_new.append(j) - - for j in current_paths_in_views: - if len(j) == 0: - current_paths_in_views_new.append(j) - continue - if j[0] != '<' and j[-1] != '>': - current_paths_in_views_new.append(j) - - if current_path_instance_new == current_paths_in_views_new: - raise KeyError( - f'The view with the path_trigger {path_trigger} already exists, coincidende path: {i.path_trigger}') - - -def view(name: str, path_trigger: str): - def decorator(func): - def wrapper(*args, **kwargs): - result = func(*args, **kwargs) # Call the original function - return result - return wrapper - return decorator diff --git a/pypulse/View/types.py b/pypulse/View/types.py new file mode 100644 index 0000000..f0144d8 --- /dev/null +++ b/pypulse/View/types.py @@ -0,0 +1,4 @@ +def int_logic(text: str): + if not text.isdigit(): + return text + return int(text) diff --git a/pypulse/View/view.py b/pypulse/View/view.py deleted file mode 100644 index ebd0608..0000000 --- a/pypulse/View/view.py +++ /dev/null @@ -1,10 +0,0 @@ -class View: - instances = [] - - def __init__(self, name: str, view: object,requirement_view:list, path_trigger: str) -> None: - self.name = name - self.view = view - self.requirement_view = requirement_view - self.path_trigger = path_trigger - - View.instances.append(self) diff --git a/pypulse/View/views.py b/pypulse/View/views.py new file mode 100644 index 0000000..4d3b9d3 --- /dev/null +++ b/pypulse/View/views.py @@ -0,0 +1,57 @@ +import os + +from pypulse.Aplication.vars import Vars +from pypulse.Utils.get_apps import applications +from pypulse.Utils.routing import is_variable, variable_info +from pypulse.View.modules import filter_views, modules +from pypulse.View.types import int_logic + +ROUTE_TYPES = { + 'INT': int_logic, + 'STR': str +} + + +def get(route: str): + apps = applications() + for app in apps: + __modules = modules(Vars.APLICATION_PATH + + os.sep + app + os.sep + 'views') + for module in __modules: + views = filter_views(module) + for view in views: + keyargs = {} + + splitted_path = route.split('/') + if splitted_path[0] == '': + del splitted_path[0] + + splitted_view_route = view.route.split('/') + if splitted_view_route[0] == '': + del splitted_view_route[0] + + for i in range(len(splitted_view_route)): + if not is_variable(splitted_view_route[i]): + continue + + if len(splitted_view_route) != len(splitted_path): + continue + + type, name = variable_info(splitted_view_route[i]) + assert type.upper( + ) in ROUTE_TYPES, f'Error at path `{view.route}`, `{type}` does not exists.' + + value = splitted_path[i] + value = ROUTE_TYPES[type.upper()](value) + keyargs[name] = value + + splitted_view_route[i] = splitted_path[i] + + if splitted_view_route == splitted_path: + return view, keyargs + + if view.route != route: + continue + + return view, None + return