Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Working Jinja2 url_for with test #1004

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open

Conversation

dave42w
Copy link
Contributor

@dave42w dave42w commented Oct 28, 2024

Description

This PR starts the process of implementing url_for so that Jinja templates can reference Robyn endpoints by function name rather than path see #996

Summary

[Updated] This PR adds a url_for that returns a fixed string and a test for this.
3rd Nov 24 Now looks up functions via the Robyn object router
7th Nov. All finished.

Changes are limited to 7 files (5 of them related to testing)

  • templating.py (define the url_for function and add it to the global Jinja environment using generic add_function_to_globals())
  • base_routes.py (call the set_robyn method of the JinjaTemplate)
  • template.html (display test output of url_for with the sync_auth function
  • test_get_requests.py (add an assert to check for /sync_auth in an href)
  • test_get_function_url (unit tests)
  • test_get_param_filled_url (unit tests)

TODO handle positional and named arguments
TODO add set_robyn and url_for to template_interface
TODO warn if no Robyn object set using set_robyn
TODO improve response to an invalid route
TODO rename from url_for to get_function_url in preparation for adding get_static_url
TODO remove @pytest.mark.url_for from test_get_requests.py`
jinja_template = JinjaTemplate(".", "utf-8") #solves my git locale pre-commit issue
TODO add unit tests
TODO add unit tests that cover combinations of url's
TODO documentation

PR Checklist

Please ensure that:

  • [X ] The PR contains a descriptive title
  • [ X] The PR contains a descriptive summary of the changes
  • [ X] You build and test your changes before submitting a PR.
  • You have added relevant documentation (I've added a docstring, until we get to the point where it can be used in a functional way I've not added it to the main documentation)
  • [ X] You have added relevant tests. We prefer integration tests wherever possible

Pre-Commit Instructions:

  • Ensure that you have run the pre-commit hooks on your PR.
    I think I've done that. I'm running the tests from a separate clone which I have had to modify to work with Python 3.12.7

Copy link

vercel bot commented Oct 28, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
robyn ✅ Ready (Inspect) Visit Preview 💬 Add feedback Nov 22, 2024 11:01pm

Copy link

codspeed-hq bot commented Oct 28, 2024

CodSpeed Performance Report

Merging #1004 will not alter performance

Comparing dave42w:url_for (d0d8e7b) with main (abb42d0)

Summary

✅ 146 untouched benchmarks

@dave42w
Copy link
Contributor Author

dave42w commented Nov 1, 2024

I'm stuck. See #996 (comment)

@dave42w dave42w changed the title Initial static text url_for implementation Working Jinja2 url_for with tests Nov 3, 2024
@dave42w dave42w changed the title Working Jinja2 url_for with tests Working Jinja2 url_for with test Nov 3, 2024
…n. ruff fixes. Safety check for no robyn object.
@sansyrox
Copy link
Member

sansyrox commented Nov 6, 2024

Hey @dave42w 👋

Is it up for review??

@dave42w
Copy link
Contributor Author

dave42w commented Nov 6, 2024

Hey @dave42w 👋

Is it up for review??

Hesitant yes. I only commit when it passes all the tests and works to a completed step.

a) by mistake I committed local changes to pyproject.toml that are needed for using uv in my python 3.12.7 environment. I'm wondering if I need to chuck this PR, create a new branch and recommit my changes without pyproject.toml?

b) this works and the tests pass but it doesn't yet support keyword parameters (eg from the examples /crime/:crime_id). I'm working on that (got distracted by drinking wine to hide from a certain set of election results). I've worked out how to do it and it's not a big job so should be done by the end of Saturday. Did you see my discord question about whether there are any restrictions on parameters to url's? It shouldn't affect this code apart from more robust error checking see https://discord.com/channels/999782964143603713/999782965460603056/1303425727227756595

c) I would appreciate feedback on what to return for error conditions (eg no call to set_robyn, no route found) I'm trying to balance informative with not leaking info useful to someone trying to penetrate the system. In many ways I'd like to use a standard httpStatus but not sure how that would work and if it would make debugging very hard (if we had a standard static 404 url I could return that).

d) I would appreciate feedback on the issue of static files see #1005 I have changed the function name that goes into the template in line with that thinking (it makes it much simpler IMHO to have separate functions to use in the template for static files and for functions rather than using a "static" argument to url_for as flask does).

So short answer, feedback would be great :-)

@dave42w
Copy link
Contributor Author

dave42w commented Nov 6, 2024

Hi @sansyrox

I've just added the support for URL parameters. All committed with tests.

So from my previous comment today b) is done. Feedback on a) c) and d) appreciated.

Thanks

Dave

@dave42w
Copy link
Contributor Author

dave42w commented Nov 7, 2024

Hi @sansyrox

I've sorted out the pyproject.toml problem (a) :-)

@dave42w
Copy link
Contributor Author

dave42w commented Nov 10, 2024

Hey @dave42w 👋

Is it up for review??

Hi,

Wondering if you are able to do that review or if there is more I need to do.

Thanks

@sansyrox
Copy link
Member

Hey @dave42w 👋

Apologies for the super late review. My work has been mental. I will try to complete my review by tonight or tomorrow for sure 😄

Comment on lines +39 to +40
@abstractmethod
def get_function_url(self, function_name: str, route_type: str = "GET", **kwargs) -> str: ...
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dave42w , should it be a part of the ABC ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put it in the ABC because I assume that if you switched from Jinja2 to a different templating engine you would still want to be able to call this function so you can have less brittle templates (ones that change if you change a subrouter prefix or the route for a function.

Comment on lines +55 to +61
def set_robyn(self, robyn: Robyn) -> None:
"""
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.
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sorry if I am being a bit daft but why is this function needed?

Copy link
Contributor Author

@dave42w dave42w Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we are rendering a template that includes a call into the TemplateInterface get_function_url(...) that function needs to get the live and complete list of routes. That means we can't have the TemplateInterface keep a copy of the routes that existed when it was created. Instead, when the call is made we check the live list of routes. The only place I could see that we can get that live list of routes from is the main app Robyn instance.

I couldn't see a way to get hold of the Robyn instance automagically. So it was either a set method or the constructor.

I decided to go for a set method as the constructor for JiujaTemplate already has 3 arguments plus self (I figured it will impact the existing code less and be easier to add additions templating packages)

If projects don't use get_function_url(...) then they don't need to call set_robyn.

Long term I want to find a way to get to the routes via a router singleton and to have the router do the work to return the URL. But I don't think we have that possibility yet. And it won't change the templates (only thing would be that set_robyn would not be needed but we can make it do nothing and depreciate it over a couple of releases)

@dave42w
Copy link
Contributor Author

dave42w commented Nov 12, 2024

@sansyrox
I haven't marked the 2 conversations as resolved as I figured you need to be happy with my responses first. Is that the right approach?

@dave42w
Copy link
Contributor Author

dave42w commented Nov 16, 2024

Hi @sansyrox
I think this is ready, just need to confirm that you are happy with my responses.

@dave42w
Copy link
Contributor Author

dave42w commented Nov 20, 2024

Hi @sansyrox I wanted to check if you are happy for the conversations to be marked as resolved?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants