From 14461b26b07e8829fe7970e1f44ee9c708624ddb Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 28 Oct 2024 22:16:46 +0000 Subject: [PATCH 01/22] Initial static text url_for implementation --- integration_tests/templates/test.html | 2 +- integration_tests/test_get_requests.py | 1 + robyn/templating.py | 11 +++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/integration_tests/templates/test.html b/integration_tests/templates/test.html index 00b2d0a1e..eb25e3263 100644 --- a/integration_tests/templates/test.html +++ b/integration_tests/templates/test.html @@ -8,6 +8,6 @@ -

{{framework}} 🤝 {{templating_engine}}

+

{{framework}} 🤝 {{templating_engine}} {{url_for()}}

diff --git a/integration_tests/test_get_requests.py b/integration_tests/test_get_requests.py index 8afa15af9..9865e958b 100644 --- a/integration_tests/test_get_requests.py +++ b/integration_tests/test_get_requests.py @@ -40,6 +40,7 @@ def check_response(r: Response): assert r.text.startswith("\n\n") assert "Jinja2" in r.text assert "Robyn" in r.text + assert "called new url_for" in r.text check_response(get(f"/{function_type}/template")) diff --git a/robyn/templating.py b/robyn/templating.py index 5cdff73e0..1da9c8de6 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -6,6 +6,16 @@ from .robyn import Headers, Response +def url_for() -> str: + """Creates a link to an endpoint function name + + NOT YET IMPLEMENTED + #TODO + #FIXME + Returns: + str: the url for the function + """ + return "called new url_for" class TemplateInterface(ABC): def __init__(self): ... @@ -17,6 +27,7 @@ def render_template(self, *args, **kwargs) -> Response: ... class JinjaTemplate(TemplateInterface): def __init__(self, directory, encoding="utf-8", followlinks=False): self.env = Environment(loader=FileSystemLoader(searchpath=directory, encoding=encoding, followlinks=followlinks)) + self.env.globals['url_for'] = url_for def render_template(self, template_name, **kwargs) -> Response: rendered_template = self.env.get_template(template_name).render(**kwargs) From 6b907b2500cbe0b5b288b1be4ac3530d0df32d5e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:33:05 +0000 Subject: [PATCH 02/22] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- robyn/templating.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/robyn/templating.py b/robyn/templating.py index 1da9c8de6..ae1d1140b 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -6,6 +6,7 @@ from .robyn import Headers, Response + def url_for() -> str: """Creates a link to an endpoint function name @@ -17,6 +18,7 @@ def url_for() -> str: """ return "called new url_for" + class TemplateInterface(ABC): def __init__(self): ... @@ -27,7 +29,7 @@ def render_template(self, *args, **kwargs) -> Response: ... class JinjaTemplate(TemplateInterface): def __init__(self, directory, encoding="utf-8", followlinks=False): self.env = Environment(loader=FileSystemLoader(searchpath=directory, encoding=encoding, followlinks=followlinks)) - self.env.globals['url_for'] = url_for + self.env.globals["url_for"] = url_for def render_template(self, template_name, **kwargs) -> Response: rendered_template = self.env.get_template(template_name).render(**kwargs) From 68d4f2ec8b582a44d674e80b49c7584d8fa23fc0 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Sun, 3 Nov 2024 20:28:47 +0000 Subject: [PATCH 03/22] Working url_for --- integration_tests/base_routes.py | 1 + integration_tests/templates/test.html | 2 +- integration_tests/test_get_requests.py | 5 +-- robyn/templating.py | 44 ++++++++++++++++++-------- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/integration_tests/base_routes.py b/integration_tests/base_routes.py index a271fb268..e4088db4b 100644 --- a/integration_tests/base_routes.py +++ b/integration_tests/base_routes.py @@ -25,6 +25,7 @@ current_file_path = pathlib.Path(__file__).parent.resolve() jinja_template = JinjaTemplate(os.path.join(current_file_path, "templates")) +jinja_template.set_robyn(app) # ===== Websockets ===== diff --git a/integration_tests/templates/test.html b/integration_tests/templates/test.html index eb25e3263..4543cf48c 100644 --- a/integration_tests/templates/test.html +++ b/integration_tests/templates/test.html @@ -8,6 +8,6 @@ -

{{framework}} 🤝 {{templating_engine}} {{url_for()}}

+

{{framework}} 🤝 {{templating_engine}} Testing url for

diff --git a/integration_tests/test_get_requests.py b/integration_tests/test_get_requests.py index 9865e958b..4de287534 100644 --- a/integration_tests/test_get_requests.py +++ b/integration_tests/test_get_requests.py @@ -32,7 +32,7 @@ def check_response(r: Response): check_response(get(f"/{function_type}/serve/html")) - +@pytest.mark.url_for @pytest.mark.benchmark @pytest.mark.parametrize("function_type", ["sync", "async"]) def test_template(function_type: str, session): @@ -40,7 +40,8 @@ def check_response(r: Response): assert r.text.startswith("\n\n") assert "Jinja2" in r.text assert "Robyn" in r.text - assert "called new url_for" in r.text + assert 'Testing url for' in r.text + check_response(get(f"/{function_type}/template")) diff --git a/robyn/templating.py b/robyn/templating.py index ae1d1140b..cc8d26d69 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -1,22 +1,13 @@ +from typing import Callable from abc import ABC, abstractmethod from jinja2 import Environment, FileSystemLoader -from robyn import status_codes +from robyn import status_codes, HttpMethod, Robyn from .robyn import Headers, Response - -def url_for() -> str: - """Creates a link to an endpoint function name - - NOT YET IMPLEMENTED - #TODO - #FIXME - Returns: - str: the url for the function - """ - return "called new url_for" +from robyn.argument_parser import Config class TemplateInterface(ABC): @@ -28,8 +19,33 @@ def render_template(self, *args, **kwargs) -> Response: ... class JinjaTemplate(TemplateInterface): def __init__(self, directory, encoding="utf-8", followlinks=False): - self.env = Environment(loader=FileSystemLoader(searchpath=directory, encoding=encoding, followlinks=followlinks)) - self.env.globals["url_for"] = url_for + self.env: Environment = Environment(loader=FileSystemLoader(searchpath=directory, encoding=encoding, followlinks=followlinks)) + self.add_function_to_globals("url_for", self.url_for) + self.robyn = None + + def add_function_to_globals(self, name: str, func: Callable): + """ + Add a global function to a Jinja environment. + """ + self.env.globals[name] = func + + def set_robyn(self, robyn: Robyn) -> None: + self.robyn: Robyn = robyn + + def url_for(self, function_name: str, route_type: HttpMethod = HttpMethod.GET) -> str: + """Creates a link to an endpoint function name + + Returns: + str: the url for the function + """ + + routes: List[Route] = self.robyn.router.get_routes() + + for r in routes: + if r.function.handler.__name__ == function_name and r.route_type == route_type: + return r.route + + return "route not found" def render_template(self, template_name, **kwargs) -> Response: rendered_template = self.env.get_template(template_name).render(**kwargs) From d0d8e7b8c56317b06781f772665040c5c3abae92 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Nov 2024 20:29:48 +0000 Subject: [PATCH 04/22] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- integration_tests/test_get_requests.py | 2 +- robyn/templating.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/integration_tests/test_get_requests.py b/integration_tests/test_get_requests.py index 4de287534..304d6a6d4 100644 --- a/integration_tests/test_get_requests.py +++ b/integration_tests/test_get_requests.py @@ -32,6 +32,7 @@ def check_response(r: Response): check_response(get(f"/{function_type}/serve/html")) + @pytest.mark.url_for @pytest.mark.benchmark @pytest.mark.parametrize("function_type", ["sync", "async"]) @@ -42,7 +43,6 @@ def check_response(r: Response): assert "Robyn" in r.text assert 'Testing url for' in r.text - check_response(get(f"/{function_type}/template")) diff --git a/robyn/templating.py b/robyn/templating.py index cc8d26d69..164a0cff4 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -7,8 +7,6 @@ from .robyn import Headers, Response -from robyn.argument_parser import Config - class TemplateInterface(ABC): def __init__(self): ... From 2a02a6a0936a79b176d0f0fad2340689bf9bdd1f Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Sun, 3 Nov 2024 20:37:40 +0000 Subject: [PATCH 05/22] Sort linter errors --- robyn/templating.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/robyn/templating.py b/robyn/templating.py index 164a0cff4..72a2e6285 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -1,9 +1,10 @@ -from typing import Callable +from typing import Callable, List from abc import ABC, abstractmethod from jinja2 import Environment, FileSystemLoader from robyn import status_codes, HttpMethod, Robyn +from router import Route from .robyn import Headers, Response From 8433c5928c558bdffe9b82f35d3b09009932f602 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 13:48:12 +0000 Subject: [PATCH 06/22] sync project.toml and poetry.lock --- pyproject.toml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 552a37ca7..32380503b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,11 +27,17 @@ dependencies = [ 'multiprocess == 0.70.14', 'nestd == 0.3.1', 'inquirerpy == 0.3.4', - 'rustimport == 1.3.4', + 'rustimport == 1.5.0', 'orjson == 3.9.15', -# conditional - "uvloop~=0.19.0; sys_platform != 'win32' and platform_python_implementation == 'CPython' and platform_machine != 'armv7l'" - ] + # conditional + "uvloop~=0.19.0; sys_platform != 'win32' and platform_python_implementation == 'CPython' and platform_machine != 'armv7l'", + "pre-commit==2.21.0", + "poetry==1.7.1", + "maturin==0.14.12", + "websocket-client==1.5.0", + "ruff==0.1.3", + "requests==2.28.2", +] [project.scripts] robyn = "robyn.cli:run" @@ -48,7 +54,7 @@ Changelog = "https://github.com/sparckles/robyn/blob/main/CHANGELOG.md" [tool.poetry] name = "robyn" -version = "0.62.1" +version = "0.63" description = "A Super Fast Async Python Web Framework with a Rust runtime." authors = ["Sanskar Jethi "] From 25df6bcc264557c5533edb654bcbfd212ab5581b Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 14:39:29 +0000 Subject: [PATCH 07/22] Corrected import for Route --- robyn/templating.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/robyn/templating.py b/robyn/templating.py index 72a2e6285..12afe324d 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -4,7 +4,7 @@ from jinja2 import Environment, FileSystemLoader from robyn import status_codes, HttpMethod, Robyn -from router import Route +from robyn.router import Route from .robyn import Headers, Response From 39dac3443314953b3cd6944091e6464603a6d638 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 14:44:34 +0000 Subject: [PATCH 08/22] Needed to run using uv --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 32380503b..26bf0c8eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,9 @@ dependencies = [ "websocket-client==1.5.0", "ruff==0.1.3", "requests==2.28.2", + "pip>=24.3.1", + "patchelf>=0.17.2.1", + "jinja2==3.0.1", ] [project.scripts] From c54238a971c31f5f08bf7acd7d86d90d7f9c3536 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 14:52:41 +0000 Subject: [PATCH 09/22] Needed to use integration tests with uv --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 26bf0c8eb..26a9a1578 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,6 +40,8 @@ dependencies = [ "pip>=24.3.1", "patchelf>=0.17.2.1", "jinja2==3.0.1", + "pytest==7.2.1", + "pytest-codspeed==1.2.2", ] [project.scripts] From 11f198a8d4f6ca2ef459b85167e71a73ffb785e3 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 14:57:29 +0000 Subject: [PATCH 10/22] remove temporary pytest mark --- integration_tests/test_get_requests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/integration_tests/test_get_requests.py b/integration_tests/test_get_requests.py index 304d6a6d4..fbaed549a 100644 --- a/integration_tests/test_get_requests.py +++ b/integration_tests/test_get_requests.py @@ -33,7 +33,6 @@ def check_response(r: Response): check_response(get(f"/{function_type}/serve/html")) -@pytest.mark.url_for @pytest.mark.benchmark @pytest.mark.parametrize("function_type", ["sync", "async"]) def test_template(function_type: str, session): From beae5ee696e5270a027f7b0189f5968ba9fa544b Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 15:09:39 +0000 Subject: [PATCH 11/22] update pytest to avoid lots of python 3.14 depreciation warnings --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 26a9a1578..01fc93273 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ dependencies = [ "pip>=24.3.1", "patchelf>=0.17.2.1", "jinja2==3.0.1", - "pytest==7.2.1", + "pytest==8.3.3", "pytest-codspeed==1.2.2", ] From 032c247512b75cffdcb3813a54ef1f0daa7ac571 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 16:26:22 +0000 Subject: [PATCH 12/22] Added abstract methodist to interface, added a docstring for set_robyn. ruff fixes. Safety check for no robyn object. --- robyn/templating.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/robyn/templating.py b/robyn/templating.py index 12afe324d..f6d0d0020 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -15,12 +15,18 @@ def __init__(self): ... @abstractmethod def render_template(self, *args, **kwargs) -> Response: ... + @abstractmethod + def set_robyn(self, robyn: Robyn) -> None: ... + + @abstractmethod + def url_for(self, function_name: str, route_type: HttpMethod = HttpMethod.GET) -> str: ... + class JinjaTemplate(TemplateInterface): - def __init__(self, directory, encoding="utf-8", followlinks=False): + def __init__(self, directory, encoding="utf-8", followlinks=False) -> None: self.env: Environment = Environment(loader=FileSystemLoader(searchpath=directory, encoding=encoding, followlinks=followlinks)) self.add_function_to_globals("url_for", self.url_for) - self.robyn = None + self.robyn: Robyn | None = None def add_function_to_globals(self, name: str, func: Callable): """ @@ -29,7 +35,13 @@ def add_function_to_globals(self, name: str, func: Callable): self.env.globals[name] = func def set_robyn(self, robyn: Robyn) -> None: - self.robyn: Robyn = robyn + """ + The url_for needs to have access to the list of routes stored in the apps Robyn object + + Args: + robyn (Robyn): The top instance of the Robyn class for this app. + """ + self.robyn = robyn def url_for(self, function_name: str, route_type: HttpMethod = HttpMethod.GET) -> str: """Creates a link to an endpoint function name @@ -38,13 +50,16 @@ def url_for(self, function_name: str, route_type: HttpMethod = HttpMethod.GET) - str: the url for the function """ + if self.robyn is None: + return "url_for needs set_robyn" + routes: List[Route] = self.robyn.router.get_routes() for r in routes: if r.function.handler.__name__ == function_name and r.route_type == route_type: return r.route - return "route not found" + return "route not found in Robyn router" def render_template(self, template_name, **kwargs) -> Response: rendered_template = self.env.get_template(template_name).render(**kwargs) From e9df6abd546fa862b6b50bdb96be36de80700a87 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 20:39:37 +0000 Subject: [PATCH 13/22] rename url_for to get_function_url & working HttpMethod arg & unit tests & fixed integration test --- integration_tests/templates/test.html | 2 +- integration_tests/test_get_requests.py | 2 +- robyn/templating.py | 15 +++---- unit_tests/test_get_function_url.py | 59 ++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 unit_tests/test_get_function_url.py diff --git a/integration_tests/templates/test.html b/integration_tests/templates/test.html index 4543cf48c..87aa59be5 100644 --- a/integration_tests/templates/test.html +++ b/integration_tests/templates/test.html @@ -8,6 +8,6 @@ -

{{framework}} 🤝 {{templating_engine}} Testing url for

+

{{framework}} 🤝 {{templating_engine}} Testing get_function_url

diff --git a/integration_tests/test_get_requests.py b/integration_tests/test_get_requests.py index fbaed549a..6d6d2fbdf 100644 --- a/integration_tests/test_get_requests.py +++ b/integration_tests/test_get_requests.py @@ -40,7 +40,7 @@ def check_response(r: Response): assert r.text.startswith("\n\n") assert "Jinja2" in r.text assert "Robyn" in r.text - assert 'Testing url for' in r.text + assert 'Testing get_function_url' in r.text check_response(get(f"/{function_type}/template")) diff --git a/robyn/templating.py b/robyn/templating.py index f6d0d0020..01ac0d698 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -3,7 +3,7 @@ from jinja2 import Environment, FileSystemLoader -from robyn import status_codes, HttpMethod, Robyn +from robyn import status_codes, Robyn from robyn.router import Route from .robyn import Headers, Response @@ -19,13 +19,13 @@ def render_template(self, *args, **kwargs) -> Response: ... def set_robyn(self, robyn: Robyn) -> None: ... @abstractmethod - def url_for(self, function_name: str, route_type: HttpMethod = HttpMethod.GET) -> str: ... + def get_function_url(self, function_name: str, route_type: str = "GET") -> str: ... class JinjaTemplate(TemplateInterface): def __init__(self, directory, encoding="utf-8", followlinks=False) -> None: self.env: Environment = Environment(loader=FileSystemLoader(searchpath=directory, encoding=encoding, followlinks=followlinks)) - self.add_function_to_globals("url_for", self.url_for) + self.add_function_to_globals("get_function_url", self.get_function_url) self.robyn: Robyn | None = None def add_function_to_globals(self, name: str, func: Callable): @@ -36,14 +36,14 @@ def add_function_to_globals(self, name: str, func: Callable): def set_robyn(self, robyn: Robyn) -> None: """ - The url_for needs to have access to the list of routes stored in the apps Robyn object + The get_function_url needs to have access to the list of routes stored in the apps Robyn object Args: robyn (Robyn): The top instance of the Robyn class for this app. """ self.robyn = robyn - def url_for(self, function_name: str, route_type: HttpMethod = HttpMethod.GET) -> str: + def get_function_url(self, function_name: str, route_type: str = "GET") -> str: """Creates a link to an endpoint function name Returns: @@ -51,12 +51,11 @@ def url_for(self, function_name: str, route_type: HttpMethod = HttpMethod.GET) - """ if self.robyn is None: - return "url_for needs set_robyn" + return "get_function_url needs set_robyn" routes: List[Route] = self.robyn.router.get_routes() - for r in routes: - if r.function.handler.__name__ == function_name and r.route_type == route_type: + if r.function.handler.__name__ == function_name and str(r.route_type) == f"HttpMethod.{route_type}": return r.route return "route not found in Robyn router" diff --git a/unit_tests/test_get_function_url.py b/unit_tests/test_get_function_url.py new file mode 100644 index 000000000..a0b08c0c3 --- /dev/null +++ b/unit_tests/test_get_function_url.py @@ -0,0 +1,59 @@ +from robyn import Robyn +from robyn.templating import JinjaTemplate + + +def h(request): + return "Hello" + + +def get_hello(request): + return "get_Hello" + + +def post_hello(request): + return "post_Hello" + + +def put_hello(request): + return "put_Hello" + + +def delete_hello(request): + return "delete_Hello" + + +def patch_hello(request): + return "patch_Hello" + + +def options_hello(request): + return "options_Hello" + + +def head_hello(request): + return "head_Hello" + + +def test_get_function_url(): + app = Robyn(__file__) + app.add_route("GET", "/", h) + app.add_route("GET", "/get_hello", get_hello) + app.add_route("POST", "/post_hello", post_hello) + app.add_route("PUT", "/put_hello", put_hello) + app.add_route("DELETE", "/delete_hello", delete_hello) + app.add_route("PATCH", "/patch_hello", patch_hello) + app.add_route("OPTIONS", "/options_hello", options_hello) + app.add_route("HEAD", "/head_hello", head_hello) + + jinja_template = JinjaTemplate(".", "templates", encoding="utf-8") + jinja_template.set_robyn(app) + + assert jinja_template.get_function_url("h") == "/" + assert jinja_template.get_function_url("get_hello") == "/get_hello" + assert jinja_template.get_function_url("get_hello", "GET") == "/get_hello" + assert jinja_template.get_function_url("post_hello", "POST") == "/post_hello" + assert jinja_template.get_function_url("put_hello", "PUT") == "/put_hello" + assert jinja_template.get_function_url("delete_hello", "DELETE") == "/delete_hello" + assert jinja_template.get_function_url("patch_hello", "PATCH") == "/patch_hello" + assert jinja_template.get_function_url("options_hello", "OPTIONS") == "/options_hello" + assert jinja_template.get_function_url("head_hello", "HEAD") == "/head_hello" From 620fb6270a748ef983eccb1483dfe74a9f44c1f5 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 21:11:11 +0000 Subject: [PATCH 14/22] encoding wasn't needed (causing me git problems with the utf-8 specified --- unit_tests/test_get_function_url.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unit_tests/test_get_function_url.py b/unit_tests/test_get_function_url.py index a0b08c0c3..042b0493b 100644 --- a/unit_tests/test_get_function_url.py +++ b/unit_tests/test_get_function_url.py @@ -45,7 +45,7 @@ def test_get_function_url(): app.add_route("OPTIONS", "/options_hello", options_hello) app.add_route("HEAD", "/head_hello", head_hello) - jinja_template = JinjaTemplate(".", "templates", encoding="utf-8") + jinja_template = JinjaTemplate(".", "templates", "utf-8") jinja_template.set_robyn(app) assert jinja_template.get_function_url("h") == "/" From a24d8e2a0f1648d64179d3d65730432718ca3dde Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 21:12:18 +0000 Subject: [PATCH 15/22] Move as much uv stuff as possible into separate sections --- pyproject.toml | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 01fc93273..0c5cbe755 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,19 +31,21 @@ dependencies = [ 'orjson == 3.9.15', # conditional "uvloop~=0.19.0; sys_platform != 'win32' and platform_python_implementation == 'CPython' and platform_machine != 'armv7l'", - "pre-commit==2.21.0", - "poetry==1.7.1", - "maturin==0.14.12", - "websocket-client==1.5.0", - "ruff==0.1.3", - "requests==2.28.2", - "pip>=24.3.1", - "patchelf>=0.17.2.1", - "jinja2==3.0.1", - "pytest==8.3.3", - "pytest-codspeed==1.2.2", + "maturin == 0.14.12", + "pip >= 24.3.1", + "patchelf == 0.17.2.1", + "jinja2 == 3.0.1", ] +[tool.uv] + +[dev] +pre-commit = "2.21.0" +poetry = "1.7.1" +websocket-client = "1.5.0" +ruff = "0.1.3" +requests = "2.28.2" + [project.scripts] robyn = "robyn.cli:run" @@ -93,7 +95,7 @@ commitizen = "2.40" optional = true [tool.poetry.group.test.dependencies] -pytest = "7.2.1" +pytest = "8.3.3" pytest-codspeed = "1.2.2" requests = "2.28.2" nox = "2023.4.22" From bfb3ca89b7fc49b4d8d611c70755f7fe5927b15c Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Mon, 4 Nov 2024 21:42:29 +0000 Subject: [PATCH 16/22] Moving pyproject.toml target --- pyproject.toml | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0c5cbe755..ce4d2874d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,17 +35,16 @@ dependencies = [ "pip >= 24.3.1", "patchelf == 0.17.2.1", "jinja2 == 3.0.1", + "types-requests>=2.32.0.20241016", + "pytest == 8.3.3", + "pytest-codspeed == 1.2.2", + "pre-commit == 2.21.0", + "poetry == 1.7.1", + "websocket-client == 1.5.0", + "ruff == 0.7.2", + "requests == 2.32.0", ] -[tool.uv] - -[dev] -pre-commit = "2.21.0" -poetry = "1.7.1" -websocket-client = "1.5.0" -ruff = "0.1.3" -requests = "2.28.2" - [project.scripts] robyn = "robyn.cli:run" @@ -95,8 +94,6 @@ commitizen = "2.40" optional = true [tool.poetry.group.test.dependencies] -pytest = "8.3.3" -pytest-codspeed = "1.2.2" requests = "2.28.2" nox = "2023.4.22" websocket-client = "1.5.0" From 79318e91d6831581f62d367b7abde4e5f9495aad Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Wed, 6 Nov 2024 23:18:42 +0000 Subject: [PATCH 17/22] support for kwargs for url's with tests --- robyn/templating.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/robyn/templating.py b/robyn/templating.py index 01ac0d698..a463ff419 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -5,10 +5,28 @@ from robyn import status_codes, Robyn from robyn.router import Route +# from robyn import robyn from .robyn import Headers, Response +def get_param_filled_url(url: str, kwdict: dict | None = None) -> str: + """fill the :params in the url + + Args: + url (str): typically comes from the route + kwdict (dict): the **kwargs as a dict + + Returns: + str: _description_modified url (if there are elements in kwdict, otherwise unchanged) + """ + if kwdict is not None: + for k, v in zip(kwdict.keys(), kwdict.values()): + url = url.replace(f":{k}", f"{v}") + + return url + + class TemplateInterface(ABC): def __init__(self): ... @@ -19,7 +37,7 @@ def render_template(self, *args, **kwargs) -> Response: ... def set_robyn(self, robyn: Robyn) -> None: ... @abstractmethod - def get_function_url(self, function_name: str, route_type: str = "GET") -> str: ... + def get_function_url(self, function_name: str, route_type: str = "GET", **kwargs) -> str: ... class JinjaTemplate(TemplateInterface): @@ -43,7 +61,7 @@ def set_robyn(self, robyn: Robyn) -> None: """ self.robyn = robyn - def get_function_url(self, function_name: str, route_type: str = "GET") -> str: + def get_function_url(self, function_name: str, route_type: str = "GET", **kwargs) -> str: """Creates a link to an endpoint function name Returns: @@ -56,6 +74,8 @@ def get_function_url(self, function_name: str, route_type: str = "GET") -> str: routes: List[Route] = self.robyn.router.get_routes() for r in routes: if r.function.handler.__name__ == function_name and str(r.route_type) == f"HttpMethod.{route_type}": + if len(kwargs) > 0: + return get_param_filled_url(r.route, kwargs) return r.route return "route not found in Robyn router" From 32836ffc6773608a0748cd44d71eb7c418fb5c43 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Wed, 6 Nov 2024 23:19:46 +0000 Subject: [PATCH 18/22] support for kwargs for url's with tests --- unit_tests/test_get_function_url.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/unit_tests/test_get_function_url.py b/unit_tests/test_get_function_url.py index 042b0493b..e27689dfc 100644 --- a/unit_tests/test_get_function_url.py +++ b/unit_tests/test_get_function_url.py @@ -57,3 +57,18 @@ def test_get_function_url(): assert jinja_template.get_function_url("patch_hello", "PATCH") == "/patch_hello" assert jinja_template.get_function_url("options_hello", "OPTIONS") == "/options_hello" assert jinja_template.get_function_url("head_hello", "HEAD") == "/head_hello" + + +def get_hello_param(request): + return "get_Hello_param" + + +def test_get_function_url_with_params() -> None: + app = Robyn(__file__) + app.add_route("GET", "/get_hello/:id", get_hello_param) + + jinja_template = JinjaTemplate(".", "templates", "utf-8") + jinja_template.set_robyn(app) + + url: str = jinja_template.get_function_url("get_hello_param", "GET", id=42) + assert url == "/get_hello/42", f"Param filled url|{url}|" From b655eba88a435f6ba0e4e5f32a8f8e05a3279c70 Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Wed, 6 Nov 2024 23:20:44 +0000 Subject: [PATCH 19/22] support for kwargs for url's with tests --- unit_tests/test_get_param_filled_url.py | 34 +++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 unit_tests/test_get_param_filled_url.py diff --git a/unit_tests/test_get_param_filled_url.py b/unit_tests/test_get_param_filled_url.py new file mode 100644 index 000000000..4ce0cd6f5 --- /dev/null +++ b/unit_tests/test_get_param_filled_url.py @@ -0,0 +1,34 @@ +from robyn.templating import get_param_filled_url + +from robyn.templating import JinjaTemplate + +# stop git local problem +_jinja_template = JinjaTemplate(".", "templates", "utf-8") + + +def test_get_param_filled_url_42() -> None: + d42: dict = {"id": 42} + assert get_param_filled_url("/get_hello/:id", d42) == "/get_hello/42" + assert get_param_filled_url("/:id", d42) == "/42" + assert get_param_filled_url("/get_hello/:idmore", d42) == "/get_hello/42more" + assert get_param_filled_url("/get_hello/:id/", d42) == "/get_hello/42/" + assert get_param_filled_url("/get_hello/:id/more", d42) == "/get_hello/42/more" + + +def test_get_param_filled_url_2s() -> None: + d42: dict = {"id": 42, "s": "str"} + assert get_param_filled_url("/get_hello/:id/:s", d42) == "/get_hello/42/str" + assert get_param_filled_url("/:id/:s", d42) == "/42/str" + assert get_param_filled_url("/get_hello/:id:smore", d42) == "/get_hello/42strmore" + assert get_param_filled_url("/get_hello/:id/:s/", d42) == "/get_hello/42/str/" + assert get_param_filled_url("/get_hello/:id/:s/more", d42) == "/get_hello/42/str/more" + assert get_param_filled_url("/get_hello/:s/:id/:s/more", d42) == "/get_hello/str/42/str/more" + + +def test_get_param_filled_url() -> None: + assert get_param_filled_url("/get_hello/:id/:s") == "/get_hello/:id/:s" + assert get_param_filled_url("/:id/:s") == "/:id/:s" + assert get_param_filled_url("/get_hello/:id:smore") == "/get_hello/:id:smore" + assert get_param_filled_url("/get_hello/:id/:s/") == "/get_hello/:id/:s/" + assert get_param_filled_url("/get_hello/:id/:s/more") == "/get_hello/:id/:s/more" + assert get_param_filled_url("/get_hello/:s/:id/:s/more") == "/get_hello/:s/:id/:s/more" From 3d93d85a740f4c8c767d93e96420bdc28fd85d6f Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Thu, 7 Nov 2024 00:01:38 +0000 Subject: [PATCH 20/22] restore pyproject --- pyproject.toml | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ce4d2874d..552a37ca7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,23 +27,11 @@ dependencies = [ 'multiprocess == 0.70.14', 'nestd == 0.3.1', 'inquirerpy == 0.3.4', - 'rustimport == 1.5.0', + 'rustimport == 1.3.4', 'orjson == 3.9.15', - # conditional - "uvloop~=0.19.0; sys_platform != 'win32' and platform_python_implementation == 'CPython' and platform_machine != 'armv7l'", - "maturin == 0.14.12", - "pip >= 24.3.1", - "patchelf == 0.17.2.1", - "jinja2 == 3.0.1", - "types-requests>=2.32.0.20241016", - "pytest == 8.3.3", - "pytest-codspeed == 1.2.2", - "pre-commit == 2.21.0", - "poetry == 1.7.1", - "websocket-client == 1.5.0", - "ruff == 0.7.2", - "requests == 2.32.0", -] +# conditional + "uvloop~=0.19.0; sys_platform != 'win32' and platform_python_implementation == 'CPython' and platform_machine != 'armv7l'" + ] [project.scripts] robyn = "robyn.cli:run" @@ -60,7 +48,7 @@ Changelog = "https://github.com/sparckles/robyn/blob/main/CHANGELOG.md" [tool.poetry] name = "robyn" -version = "0.63" +version = "0.62.1" description = "A Super Fast Async Python Web Framework with a Rust runtime." authors = ["Sanskar Jethi "] @@ -94,6 +82,8 @@ commitizen = "2.40" optional = true [tool.poetry.group.test.dependencies] +pytest = "7.2.1" +pytest-codspeed = "1.2.2" requests = "2.28.2" nox = "2023.4.22" websocket-client = "1.5.0" From f6193ea9fd4f4df91835bbdd2f42c216a06f385f Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Thu, 21 Nov 2024 00:22:58 +0000 Subject: [PATCH 21/22] Fix linter complaints --- robyn/templating.py | 5 ++--- unit_tests/test_get_param_filled_url.py | 5 ----- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/robyn/templating.py b/robyn/templating.py index a463ff419..1494aba30 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -1,11 +1,10 @@ -from typing import Callable, List from abc import ABC, abstractmethod +from typing import Callable, List from jinja2 import Environment, FileSystemLoader -from robyn import status_codes, Robyn +from robyn import Robyn, status_codes from robyn.router import Route -# from robyn import robyn from .robyn import Headers, Response diff --git a/unit_tests/test_get_param_filled_url.py b/unit_tests/test_get_param_filled_url.py index 4ce0cd6f5..aeb24492f 100644 --- a/unit_tests/test_get_param_filled_url.py +++ b/unit_tests/test_get_param_filled_url.py @@ -1,10 +1,5 @@ from robyn.templating import get_param_filled_url -from robyn.templating import JinjaTemplate - -# stop git local problem -_jinja_template = JinjaTemplate(".", "templates", "utf-8") - def test_get_param_filled_url_42() -> None: d42: dict = {"id": 42} From 14e57c51235b9261f31709cd9cb79178ebf859ae Mon Sep 17 00:00:00 2001 From: Dave Warnock Date: Sat, 30 Nov 2024 23:53:43 +0000 Subject: [PATCH 22/22] fix: Use Union for python 3.8 compatibility instead of | --- robyn/templating.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/robyn/templating.py b/robyn/templating.py index 1494aba30..2f23204c7 100644 --- a/robyn/templating.py +++ b/robyn/templating.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Callable, List +from typing import Callable, List, Union from jinja2 import Environment, FileSystemLoader @@ -9,7 +9,7 @@ from .robyn import Headers, Response -def get_param_filled_url(url: str, kwdict: dict | None = None) -> str: +def get_param_filled_url(url: str, kwdict: Union[dict, None] = None) -> str: """fill the :params in the url Args: @@ -43,7 +43,7 @@ class JinjaTemplate(TemplateInterface): def __init__(self, directory, encoding="utf-8", followlinks=False) -> None: self.env: Environment = Environment(loader=FileSystemLoader(searchpath=directory, encoding=encoding, followlinks=followlinks)) self.add_function_to_globals("get_function_url", self.get_function_url) - self.robyn: Robyn | None = None + self.robyn: Union[Robyn, None] = None def add_function_to_globals(self, name: str, func: Callable): """