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
V2routing #37
Conversation
Awesome! I'll check out the new implementation. |
@sanic-org/framework thoughts? I'd like to release this as a |
That review was only for the docs, not the other changes (not sure how I approving 2 reviewed files ended up approving 8 others without Github showing them to me). |
"str": (str, re.compile(r"^[^/]+$")), | ||
"slug": (slug, re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")), | ||
"alpha": (alpha, re.compile(r"^[A-Za-z]+$")), | ||
"path": (str, re.compile(r"^[^/]?.*?$")), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the path regex correct? What's that trickery with optional initial non-slash?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have some tests for this here: https://github.com/sanic-org/sanic/blob/main/tests/test_routes.py#L582
TBH, I cannot recall the reason for making it optional. The commit is here: 87d8ada
It does seem like we can probably just remove it completely. Will need to do more testing though.
sanic_routing/route.py
Outdated
list(self.router.regex_types.keys()).index(label) | ||
if label in self.router.regex_types | ||
else 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is at index 0 of that map? String type, presumably, but a comment here would be helpful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if the code is reworked slightly it becomes self-documenting:
is_regex = label not in self.router.regex_types
priority = (
0
if is_regex
else list(self.router.regex_types.keys()).index(label)
)
self._params[idx] = ParamInfo(
name, raw_path, label, cast, pattern, is_regex, priority
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed everything except the code generation in tree.py. Mostly stylistic issues, possibly minor bugs but no algorithmic problems that I could find so far.
I'd suggest implementing a helper class for code generation that internally keeps track of indentation to avoid manual indent management and all the clutter that comes with Line objects etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
What do you have in mind: source.add("#code at same indent")
source.add("#code indent one", 1)
source.add("#code dedent one", -1)
source.add("#code specifically at indentation=1", at=1) Not a bad idea, because we could do entire blocks: source.add(f"""
try:
something({args})
except Exception:
...
""") I did have a version of it using the I think this is worthy of a ticket for future refactor, not now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than the odd ellipsis, looks good.
sanic_routing/router.py
Outdated
else: | ||
... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this?
Re code generation: maybe take that a step forward and use actual inline Python code instead of string literals. Code that is syntactically valid can be loaded even if the variables don't exist, provided that the particular path never gets executed. Annotations or some other hacks could be used to inject parts into it. Well, you get the idea but this is becoming some true black magic by now. # This is router code
if need_foo:
with codegen:
# This is generated code
if route == "foo":
return handler_foo |
Strings allow interpolation. If we prefer a code based option, I'd be more favorable towards AST. An option worth keeping on the table. |
This is a pretty thorough overhaul of how the dynamic paths generated. The concept is largely still the same, but with this methodology we can take out some of the more hacky bits re: indentations. Also, in my testing it covers a wider array of edge cases including #35.
This also closes the loop on a few items including:
alpha
andstring
param typesslug
param type<foo:string>
in favor of<foo:str>
<foo:number>
in favor of<foo:float>
route.uri
accessorFixes #35
Fixes #32
Resolves #34
Resolves #12
Resolves #11
Closes #28