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
Enhancement: Rust, C or C++ bindings for path resolution #177
Comments
Some links to the existing code in starlite would be helpful to start. Also, have you considered/tried compiling starlite/parts of it with mypyc? |
100% this. I'd love to see what the solution looks like in modern cython (i say modern because the last time I built anything of consequence with cython was before typing was really a thing) and mypyc. Thinking about this issue on the next meta level up, an overall efficiency analysis of the two main things
|
Don't get me wrong, I'd also like to see what the solution looks like with py03 and rust too though 😆 It would be good for developer docs to have a diagram of that "radix prefix tree" pattern included. I'm glad you mentioned that @Goldziher as the code is a bit hard to follow (not a criticism but just by nature) - is that the algo in |
I did some trials with cython and mypyc. Mypyc Didn't like async and some other stuff, so it could handle some parts of the codebase and not others. Cython required quite a few changes to the code to get the compiled code to actually work. I'm not against this, but for my money these solutions are a compromise - offering a performance boost, but less so than native code. As to code snippets, diagrams etc. Sure, I'll do this later today. |
Thanks! |
Was this trying to cythonize/mypycize the whole lib? Or just targeted stuff? |
Both. I had more success with cython, but the performance boost wasn't great. The main issue for compiling the entire lib is pydantic - pydantic has cython, so if you install cython as part of your dependencies it will compile, giving you a speed boost. But any code that uses pydantic cannot be compiled itself. |
So, lets start with code. The most updated version is the one in #173, so I will explain the code as it appears there which will also help by and by with the review of that PR. There are two files that interest here - def register(self, value: ControllerRouterHandler) -> None: # type: ignore[override]
"""
Register a Controller, Route instance or RouteHandler on the app.
Calls Router.register() and then creates a signature model for all handlers.
"""
routes = super().register(value=value)
for route in routes:
if isinstance(route, HTTPRoute):
route_handlers = route.route_handlers
else:
route_handlers = [cast(Union[WebSocketRoute, ASGIRoute], route).route_handler] # type: ignore
for route_handler in route_handlers:
self.create_handler_signature_model(route_handler=route_handler)
route_handler.resolve_guards()
route_handler.resolve_middleware()
if isinstance(route_handler, HTTPRouteHandler):
route_handler.resolve_response_class()
route_handler.resolve_before_request()
route_handler.resolve_after_request()
if isinstance(route, HTTPRoute):
route.create_handler_map()
elif isinstance(route, WebSocketRoute):
route.handler_parameter_model = route.create_handler_kwargs_model(route.route_handler)
self.construct_route_map() This method is called in the Note: This method is exposed to allow dynamic registeration of routes - even after app initialization. The The problem with this approach, which is btw also the same in the NodeJS framework Express and other popular non-python frameworks, is that it doesn't scale well. The more routes you have, the longer matching can take because each regex is tested against the incoming request's path. In other words - time complexity is not good. Saying that, the one advantage this method does have in python is that the python regex engine is implemented in C, so its quite fast in comparison with normal python code. You will not see a significant difference in small apps with only a few routes, only with large apps. Still, I found this to be a bad design choice and decided to move away from it. What does I decided to implement this using python dictionaries and combine it with sets, because of the particulars of how python implements these - dictionary key lookup is fast because it uses sets behind the scenes, while dictionary value access is faster than iteration, and sets are fast because they are implemented natively, with set lookup being exceptionally fast in python (respective of python that is). This is basically whats happening inside the def construct_route_map(self) -> None:
"""
Create a map of the app's routes. This map is used in the asgi router to route requests.
"""
if "_components" not in self.route_map:
self.route_map["_components"] = set()
for route in self.routes:
path = route.path
if route.path_parameters or path in self.static_paths:
for param_definition in route.path_parameters:
path = path.replace(param_definition["full"], "")
path = path.replace("{}", "*")
cur = self.route_map
components = ["/", *[component for component in path.split("/") if component]]
for component in components:
components_set = cast(Set[str], cur["_components"])
components_set.add(component)
if component not in cur:
cur[component] = {"_components": set()}
cur = cast(Dict[str, Any], cur[component])
else:
self.route_map[path] = {"_components": set()}
self.plain_routes.add(path)
cur = self.route_map[path]
if "_path_parameters" not in cur:
cur["_path_parameters"] = route.path_parameters # <- this is a set stored on each route instance
if "_asgi_handlers" not in cur:
cur["_asgi_handlers"] = {} # dict[str, ASGIApp]
if "_is_asgi" not in cur:
cur["_is_asgi"] = False # bool
if path in self.static_paths:
cur["static_path"] = path # str
cur["_is_asgi"] = True
asgi_handlers = cast(Dict[str, ASGIApp], cur["_asgi_handlers"])
# construct an ASGIApp for the given route (path, or path + method for http)
if isinstance(route, HTTPRoute):
for method, handler_mapping in route.route_handler_map.items():
handler, _ = handler_mapping
asgi_handlers[method] = self.build_route_middleware_stack(route, handler)
elif isinstance(route, WebSocketRoute):
asgi_handlers["websocket"] = self.build_route_middleware_stack(route, route.route_handler)
elif isinstance(route, ASGIRoute):
asgi_handlers["asgi"] = self.build_route_middleware_stack(route, route.route_handler)
cur["_is_asgi"] = True The above code creates a tree structure with each node of the tree being identified by a path componen, containing data about any routes belonging to it and allowing access to child nodes via their respective path component. Lets consider an example from the tests: def test_handler_multi_paths() -> None:
@get(path=["/", "/something", "/{some_id:int}", "/something/{some_id:int}"], media_type=MediaType.TEXT)
def handler_fn(some_id: int = 1) -> str:
assert some_id
return str(some_id)
with create_test_client(handler_fn) as client:
# .... If we inspect in the debugger the kind of mapping that is created above, we see this: {
'_components':{
'/'
},
'/':{
'_components':{
'something',
'*'
},
'_path_parameters':[
],
'_asgi_handlers':{
'GET':<bound method HTTPRoute.handle of <starlite.routes.HTTPRoute object at 0x106592ea0>>
},
'_is_asgi':False,
'*':{
'_components':set(),
'_path_parameters':[
{
'name':'some_id',
'type':<class'int'>,
'full':'some_id:int'
}
],
'_asgi_handlers':{
'GET':<bound method HTTPRoute.handle of <starlite.routes.HTTPRoute object at 0x106593760>>
},
'_is_asgi':False
},
'something':{
'_components':{
'*'
},
'*':{
'_components':set(),
'_path_parameters':[
{
'name':'some_id',
'type':<class'int'>,
'full':'some_id:int'
}
],
'_asgi_handlers':{
'GET':<bound method HTTPRoute.handle of <starlite.routes.HTTPRoute object at 0x106593a00>>
},
'_is_asgi':False
}
}
},
'/something':{
'_components':set(),
'_path_parameters':[
],
'_asgi_handlers':{
'GET':<bound method HTTPRoute.handle of <starlite.routes.HTTPRoute object at 0x1065937d0>>
},
'_is_asgi':False
}
} This brings us to the last method in the def build_route_middleware_stack(
self, route: Union[HTTPRoute, WebSocketRoute, ASGIRoute], route_handler: BaseRouteHandler
) -> ASGIApp:
"""Constructs a middleware stack that serves as the point of entry for each route"""
asgi_handler: ASGIApp = route.handle
for middleware in route_handler.resolve_middleware():
if isinstance(middleware, StarletteMiddleware):
asgi_handler = middleware.cls(app=asgi_handler, **middleware.options)
else:
asgi_handler = middleware(app=asgi_handler)
if self.allowed_hosts:
asgi_handler = TrustedHostMiddleware(app=asgi_handler, allowed_hosts=self.allowed_hosts)
if self.cors_config:
asgi_handler = CORSMiddleware(app=asgi_handler, **self.cors_config.dict())
return asgi_handler This method creates the This now brings us to how these paths are resolved. This happens in the async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
scope["app"] = self
if scope["type"] == "lifespan":
await self.asgi_router.lifespan(scope, receive, send)
return
try:
scope["state"] = {}
await self.asgi_router(scope, receive, send) # <-- this is the call
except Exception as e: # pylint: disable=broad-except
await self.handle_exception(scope=scope, receive=receive, send=send, exc=e) And this is whats happening there: def parse_scope_to_route(self, scope: Scope) -> Tuple[Dict[str, ASGIApp], bool]:
"""
Given a scope object, traverse the route mapping and retrieve the correct "leaf" in the route tree.
"""
path_params: List[str] = []
path = cast(str, scope["path"]).strip()
if path != "/" and path.endswith("/"):
path = path.rstrip("/")
if path in self.app.plain_routes:
cur: Dict[str, Any] = self.app.route_map[path]
else:
cur = self.app.route_map
components = ["/", *[component for component in path.split("/") if component]]
for component in components:
components_set = cast(Set[str], cur["_components"])
if component in components_set:
cur = cast(Dict[str, Any], cur[component])
continue
if "*" in components_set:
path_params.append(component)
cur = cast(Dict[str, Any], cur["*"])
continue
if cur.get("static_path"):
static_path = cast(str, cur["static_path"])
if static_path != "/":
scope["path"] = scope["path"].replace(static_path, "")
continue
raise NotFoundException()
scope["path_params"] = (
parse_path_params(cur["_path_parameters"], path_params) if cur["_path_parameters"] else {}
)
asgi_handlers = cast(Dict[str, ASGIApp], cur["_asgi_handlers"])
is_asgi = cast(bool, cur["_is_asgi"])
return asgi_handlers, is_asgi
@staticmethod
def resolve_asgi_app(scope: Scope, asgi_handlers: Dict[str, ASGIApp], is_asgi: bool) -> ASGIApp:
"""
Given a scope, retrieves the correct ASGI App for the route
"""
if is_asgi:
return asgi_handlers[ScopeType.ASGI]
if scope["type"] == ScopeType.HTTP:
if scope["method"] not in asgi_handlers:
raise MethodNotAllowedException()
return asgi_handlers[scope["method"]]
return asgi_handlers[ScopeType.WEBSOCKET]
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
"""
The main entry point to the Router class.
"""
try:
asgi_handlers, is_asgi = self.parse_scope_to_route(scope=scope)
asgi_handler = self.resolve_asgi_app(scope=scope, asgi_handlers=asgi_handlers, is_asgi=is_asgi)
except KeyError as e:
raise NotFoundException() from e
await asgi_handler(scope, receive, send) As you can see, the call method first calls def parse_scope_to_route(self, scope: Scope) -> Tuple[Dict[str, ASGIApp], bool]:
"""
Given a scope object, traverse the route mapping and retrieve the correct "leaf" in the route tree.
"""
path_params: List[str] = [] # stored path params, we append them as we find them when traversing
path = cast(str, scope["path"]).strip()
if path != "/" and path.endswith("/"): # normalize the path - we do not care for trailing slashes
path = path.rstrip("/")
# the path is a "plain_route", meaning it has no path params, e.g. "/companies"
# we therefore do not need to traverse the map and can simply use the normalized path as a key
if path in self.app.plain_routes:
cur: Dict[str, Any] = self.app.route_map[path]
else: # we got here, which means the path we got is parameterized
# we traversing the map via looping, each time we move a level, cur is going to be updated
cur = self.app.route_map
components = ["/", *[component for component in path.split("/") if component]]
# for "/foo/123/buzz" we will have here ["/", "foo", "123", "buzz"]
for component in components:
# we are taking the component set we have, because its the fastest lookup
components_set = cast(Set[str], cur["_components"])
# if the component we have here is not a parameter, it should match, e.g. ["/", "foo", "buzz"]
if component in components_set:
# update cur to the next level
cur = cast(Dict[str, Any], cur[component])
continue
# we have an "*" in the component_set, we therefore allow for a parameter
if "*" in components_set:
# we got to this point with the value "123", and we appent it to the path components
path_params.append(component)
# update cur to the next level
cur = cast(Dict[str, Any], cur["*"])
continue
# special case for static paths
if cur.get("static_path"):
static_path = cast(str, cur["static_path"])
if static_path != "/":
scope["path"] = scope["path"].replace(static_path, "")
continue
# no matches, raise 404
raise NotFoundException()
# we use a helper function to transform url params, which are always strings, into their values.
scope["path_params"] = (
parse_path_params(cur["_path_parameters"], path_params) if cur["_path_parameters"] else {}
)
asgi_handlers = cast(Dict[str, ASGIApp], cur["_asgi_handlers"])
is_asgi = cast(bool, cur["_is_asgi"])
return asgi_handlers, is_asgi Once the map has been traversed to the correct node - and if no exception has been raise - the {
'_asgi_handlers':{
'GET':<bound method HTTPRoute.handle of <starlite.routes.HTTPRoute object at 0x106592ea0>>
},
'_is_asgi':False,
} Additionally, the resolved path params have been injected into the Finally, the actual handler is resolved in the method def resolve_asgi_app(scope: Scope, asgi_handlers: Dict[str, ASGIApp], is_asgi: bool) -> ASGIApp:
"""
Given a scope, retrieves the correct ASGI App for the route
"""
if is_asgi:
return asgi_handlers[ScopeType.ASGI]
if scope["type"] == ScopeType.HTTP:
if scope["method"] not in asgi_handlers:
raise MethodNotAllowedException()
return asgi_handlers[scope["method"]]
return asgi_handlers[ScopeType.WEBSOCKET] This method simply uses data in the SummarySo as you can see above route resolution happens using a tree structure. The advantage of this approach is that route handlers are grouped in nodes, or branches, with shared path components serving as prefixes. This scales horizontally (number of total routes) a lot better than regexes and is a good datastruture for handling addresses and urls. It does not scale so well when there are a lot of url parameters involved, because this requires a lot of traversal. Still, all in all I assume that the most applications will not have a huge number of url parameters and will tend to have more routes than complex urls. I tried to make this as efficent as i knew how using python. Still, the traversal of the paths is limited by the runtime speed of python. This can probably be enhanced using a native binding, but I cannot say how much etc. |
Wow @Goldziher - that's comprehensive! I'll take the time to review when I have some time and if I have any questions I'll ping you in discord. Cheers. |
@vrslev read up my explanation above, it will clarify the code you were looking at |
Thanks! |
I think I might want to give a crack at this. Which do you think would be better, making this part of starlite or placing the tree code in a serperate repository? Here are some example Radix trees: Rax and radix_tree. |
Go for it. How drastic will the perf difference be? If it's small, say 10-20 percent, I'd say maintainability is paramount and thus c++ would be better. Please use the same repository. We will need to create a testing setup for this code as well I guess. |
Could you give some insights on why you're leaning towards C++ and not Rust? The later seems like a default modern choice now and I'm surprised to see that it's not. For example, orjson is written in Rust so is pydantic-core. Rust is growing in popularity and I often see it as C++ substitute. So doesn't it make more sense to use it? |
I think it's just byproduct of the domain knowledge of the people sticking up their hands to have a crack at it. No bias against rust, nor any requirement that we only make one implementation before we lock something in. |
I'll give writing the bindings in Rust a shot. |
To clarify, I'm envisioning something like: AnyRoute = Union[WebSocketRoute, ASGIRoute, HTTPRoute]
class RouteMap:
def __init__(self): ...
def add_routes(self, routes: Collection[AnyRoute]): ...
def resolve_route(self, scope: Scope) -> ASGIRoute: ... implemented as a compiled extension. Does that seem accurate? |
Pretty much |
I had a go at trying to extract out such an interface in python first: https://github.com/Dr-Emann/starlite/blob/refactor_route_map/starlite/route_map.py Unfortunately, I did find that I needed access to a Is there an existing way to benchmark the routing, ideally by itself, or if not, an easy set-up? Finally, a note about the difference between regex matching and this trie method: while the standard way of matching many regex-en against a string would be to try each regex in sequence, it's possible, depending on the regex engine, to compile a whole set of regexes together, and match on them all simultaneously, returning which one(s) matched. Given how optimized regex engines tend to be, I'd be interested in a comparison of trying to resolve the routes in that way, as well. |
That's great! So there is no test setup for this at present I'm afraid. And yes, testing compiled regexes is a good idea . |
I've ported the logic for the route map to a Rust extension very directly using the same trie method, but with a Rust struct containing The code passes all As for the package/release side of things, the Rust-Python interop uses PyO3, and builds with Maturin. I added an empty build script (though I'm not sure if it's necessary?) and set it up to run in One potential issue with the current Rust implementation is that it needs handles to the function The Python interface for the route map is here. Please let me know if there are any issues / things that need to be added. |
First off - many thanks. It seems there are now two possible implementations in place. What I suggest is that you add a PR with your changes. We will review it, and get it merged into a special branch in Starlite other than main. This will our baseline for the rust bindings and we can then then work on benchmarking. We need build scripts and unit tests as well. What do you guys think? @Dr-Emann @nramos0 @peterschutt |
Here's my implementation (in C): https://github.com/MrAwesomeRocks/starlite/blob/NinoMaruszewski/issue-177-c-bindings/starlite/routing/. The pure-python part ( |
Thanks @MrAwesomeRocks. We will be going with Rust though, and work on the open PR as a basis. It's the best course of action for two reasons- 1. That implementation has a complete draft, and 2. Rust is easier to maintain for us in the long run and is as such future proofing. You're welcome to chime there if course. |
* add route map extension * change maturin to dev dependency * rust ext: make Node::is_asgi default to false * rust ext: remove unused dependency * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Move rust extension out of starlite folder * Correct import * Include rust source in sdist build * Working extension poetry build * Rename build.py * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * rust ext: remove some uses of `Python::acquire_gil()` * rust ext: don't return `PyResult` for infallible operations * rust ext: hide plain route methods from python interface * rust ext: add route collection parameter to `add_routes` * rust ext: use `IntoPy` trait method for `Node` instead of `as_pydict` * rust ext: refactor parameters for `configure_route_map_node` * rust ext: remove outdated comment * rust_ext: change uses of `cur` to `cur_node` * rust ext: fix typo in route map comments * rust ext: downgrade add_node_to_route_map return value to shared ref * rust_ext: port build_route_middleware_stack into extension util, removing starlite instance dependence * rust ext: add minimal test * Enhancement: Brotli compression middleware (#252) * FEATURE: Added Compression Middleware - Existing Gzip Middleware - Brotli with an optional Gzip fallback. * 1.5.4 * updated pyproject.toml to exclude lines form coverage report * Add tests for `Starlite.construct_route_map` * Address flake8 validation rules * Removes `uuid4()` from within parametrized test cases. Vscode test discovery caches the test case names including parametrized values. This makes having `uuid4()` calls in the parametrized test cases an issue as vscode shows test case failures when it cannot find test cases that it has previously resolved. As the change doesn't affect the utility of the test, it is better to fix the case for vscode users so we don't get the same issue reported in the future. * Addresses cognitive complexity of `DTOFactory.__call__()` by breaking nested logic out into helper methods. Changes no logic, test cov still 100% and existing tests pass. For #203 * updated dependencies * Issue 187 layered parameters (#261) * feat: added parameters to all app layers * feat: refactored handler layer resolution logic * chore: cleanup signature modelling * feat: add layered parameters to kwargs model * fix test coverage * skipped failing test in py 3.7 * update OA params * updated implementation to use ModelField insteam of FieldInfo * add openapi parameter tests * add docs * 1.6.0 * 1.6.1 * Fix route-map path existence test logic (#275) (#277) * added after_response (#279) * added after_response * addressed review comments * Issue 188: resolve exceptions swallowing args (#281) * updated exception init * add tests * 1.6.2 * chore: updated maintainer list (#285) * docs: add cofin as a contributor for maintenance (#286) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Issue #255: allow single element query param in sequence types (#262) * Array handling in query params * Refactor array handling Co-authored-by: Joseph Daniel <jdn@logpoint.com> * docs: add josepdaniel as a contributor for code (#290) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Updates instructions to install `testing` extra. * LifecycleHook improvements. - Adds `LifecycleHook` for eager evaluation of sync vs async callables and centralisation of handler resolution. Generic on handler response. - Adds aliases `AfterRequestHook`, `AfterResponseHook`, `BeforeRequestHook` that are strongly typed to appropriate handler response type. - Adds support for lifecycle hooks that are instance methods by overwriting handlers assigned to class variables on `Controller` only if they are originally functions. Closes #284 * Enhancement: Tortoise-ORM Plugin (#283) * added tortoise to dev dependencies * added base plugin implementation * add tests * updated plugin implementation * cleanup dependencies * updated implementation * fixed issues * resolved issues * add openapi support * fix tests * updated tests * add docs * fix linter issues * updated tests * 1.7.0 * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity (#292) * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity * Make `openapi.create_paramter_for_handler`'s helper functions public * Revise misleading `openapi.get_recursive_handler_parameters` docstrings * Adds `exceptions.utils.create_exception_response()`. - makes `starlite.exceptions` a sub-package with same api as module it replaces. - adds `starlite.exceptions.utils` module to house the response generation helper function. * Supress warning generated from Tortoise ORM DTO test case. Warning: `RuntimeWarning: coroutine 'TortoiseORMPlugin.to_dict' was never awaited` The warning is expected for the underlying code logic and test case, so safe to supress. * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] * Fixes `!!! important` block and adds `<!-- prettier-ignore -->`. * `orjson` use in `WebSocket.{receive,send}_json()` Implementations are functionally the same as upstream except for orjson usage and we raise our own exceptions. Adds tests for `connection.WebSocket`. Creates `tests/connection` and moved `tests/request` to that location. * Support for SwaggerUI (#302) (#303) * Support for SwaggerUI (#302) * Support for SwaggerUI As per #300 * Use built-in copy method * Add basic sanity check tests for ReDoc and Swagger UI routes (#304) Tests for #303 / #302 These tests check whether the UI handlers: - don't throw an Exception - return 200 OK - return HTML of some form * updated urls, add docs * fix memoization issue Co-authored-by: Tim Wedde <timwedde@icloud.com> * 1.7.1 * Allow Partial to annotate fields of nested classes (#288) * Allow Partial to annotate fields for superclasses * added test to ensure __annotations__ are resolved from parent classes * added test for runtime behaviour of Partial on classes that don't inherit from pydantic.BaseModel * use typing.get_type_hints() instead of __annotations__ for getting class type annotations * raise ImproperlyConfiguredException if class passed to Partial doesn't inherit from BaseModel * added test to ensure Partial raises ImproperlyConfiguredException if an invalid class is given * added Partial section to DTO docs * docs: add Harry-Lees as a contributor for code, doc (#305) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * update docs * Tidy grammar in comment. * `OpenAPIConfig.use_handler_docstrings` Adds ability to configure openapi schema generation to use the route handler docstring for operation description. If `False` docstrings are ignored, this is default behavior for backward compatibility. If `True`, `HTTPRouteHandler.description` takes precedence if set, otherwise the docstring is used. * Adds detail to exception raised during signature model creation. * 1.7.2 * add route map extension * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Correct import * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * fix some issues caused when rebasing Co-authored-by: Zachary Dremann <dremann@gmail.com> Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com> Co-authored-by: Na'aman Hirschfeld <nhirschfeld@gmail.com> Co-authored-by: Dane Solberg <danesolberg@gmail.com> Co-authored-by: Peter Schutt <peter@topsport.com.au> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: josepdaniel <36941460+josepdaniel@users.noreply.github.com> Co-authored-by: Joseph Daniel <jdn@logpoint.com> Co-authored-by: cătălin <catalin@roboces.dev> Co-authored-by: Peter Schutt <peter.github@proton.me> Co-authored-by: Tim Wedde <timwedde@icloud.com> Co-authored-by: Harry <harry.lees@gmail.com>
* add route map extension * change maturin to dev dependency * rust ext: make Node::is_asgi default to false * rust ext: remove unused dependency * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Move rust extension out of starlite folder * Correct import * Include rust source in sdist build * Working extension poetry build * Rename build.py * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * rust ext: remove some uses of `Python::acquire_gil()` * rust ext: don't return `PyResult` for infallible operations * rust ext: hide plain route methods from python interface * rust ext: add route collection parameter to `add_routes` * rust ext: use `IntoPy` trait method for `Node` instead of `as_pydict` * rust ext: refactor parameters for `configure_route_map_node` * rust ext: remove outdated comment * rust_ext: change uses of `cur` to `cur_node` * rust ext: fix typo in route map comments * rust ext: downgrade add_node_to_route_map return value to shared ref * rust_ext: port build_route_middleware_stack into extension util, removing starlite instance dependence * rust ext: add minimal test * Enhancement: Brotli compression middleware (#252) * FEATURE: Added Compression Middleware - Existing Gzip Middleware - Brotli with an optional Gzip fallback. * 1.5.4 * updated pyproject.toml to exclude lines form coverage report * Add tests for `Starlite.construct_route_map` * Address flake8 validation rules * Removes `uuid4()` from within parametrized test cases. Vscode test discovery caches the test case names including parametrized values. This makes having `uuid4()` calls in the parametrized test cases an issue as vscode shows test case failures when it cannot find test cases that it has previously resolved. As the change doesn't affect the utility of the test, it is better to fix the case for vscode users so we don't get the same issue reported in the future. * Addresses cognitive complexity of `DTOFactory.__call__()` by breaking nested logic out into helper methods. Changes no logic, test cov still 100% and existing tests pass. For #203 * updated dependencies * Issue 187 layered parameters (#261) * feat: added parameters to all app layers * feat: refactored handler layer resolution logic * chore: cleanup signature modelling * feat: add layered parameters to kwargs model * fix test coverage * skipped failing test in py 3.7 * update OA params * updated implementation to use ModelField insteam of FieldInfo * add openapi parameter tests * add docs * 1.6.0 * 1.6.1 * Fix route-map path existence test logic (#275) (#277) * added after_response (#279) * added after_response * addressed review comments * Issue 188: resolve exceptions swallowing args (#281) * updated exception init * add tests * 1.6.2 * chore: updated maintainer list (#285) * docs: add cofin as a contributor for maintenance (#286) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Issue #255: allow single element query param in sequence types (#262) * Array handling in query params * Refactor array handling Co-authored-by: Joseph Daniel <jdn@logpoint.com> * docs: add josepdaniel as a contributor for code (#290) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Updates instructions to install `testing` extra. * LifecycleHook improvements. - Adds `LifecycleHook` for eager evaluation of sync vs async callables and centralisation of handler resolution. Generic on handler response. - Adds aliases `AfterRequestHook`, `AfterResponseHook`, `BeforeRequestHook` that are strongly typed to appropriate handler response type. - Adds support for lifecycle hooks that are instance methods by overwriting handlers assigned to class variables on `Controller` only if they are originally functions. Closes #284 * Enhancement: Tortoise-ORM Plugin (#283) * added tortoise to dev dependencies * added base plugin implementation * add tests * updated plugin implementation * cleanup dependencies * updated implementation * fixed issues * resolved issues * add openapi support * fix tests * updated tests * add docs * fix linter issues * updated tests * 1.7.0 * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity (#292) * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity * Make `openapi.create_paramter_for_handler`'s helper functions public * Revise misleading `openapi.get_recursive_handler_parameters` docstrings * Adds `exceptions.utils.create_exception_response()`. - makes `starlite.exceptions` a sub-package with same api as module it replaces. - adds `starlite.exceptions.utils` module to house the response generation helper function. * Supress warning generated from Tortoise ORM DTO test case. Warning: `RuntimeWarning: coroutine 'TortoiseORMPlugin.to_dict' was never awaited` The warning is expected for the underlying code logic and test case, so safe to supress. * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] * Fixes `!!! important` block and adds `<!-- prettier-ignore -->`. * `orjson` use in `WebSocket.{receive,send}_json()` Implementations are functionally the same as upstream except for orjson usage and we raise our own exceptions. Adds tests for `connection.WebSocket`. Creates `tests/connection` and moved `tests/request` to that location. * Support for SwaggerUI (#302) (#303) * Support for SwaggerUI (#302) * Support for SwaggerUI As per #300 * Use built-in copy method * Add basic sanity check tests for ReDoc and Swagger UI routes (#304) Tests for #303 / #302 These tests check whether the UI handlers: - don't throw an Exception - return 200 OK - return HTML of some form * updated urls, add docs * fix memoization issue Co-authored-by: Tim Wedde <timwedde@icloud.com> * 1.7.1 * Allow Partial to annotate fields of nested classes (#288) * Allow Partial to annotate fields for superclasses * added test to ensure __annotations__ are resolved from parent classes * added test for runtime behaviour of Partial on classes that don't inherit from pydantic.BaseModel * use typing.get_type_hints() instead of __annotations__ for getting class type annotations * raise ImproperlyConfiguredException if class passed to Partial doesn't inherit from BaseModel * added test to ensure Partial raises ImproperlyConfiguredException if an invalid class is given * added Partial section to DTO docs * docs: add Harry-Lees as a contributor for code, doc (#305) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * update docs * Tidy grammar in comment. * `OpenAPIConfig.use_handler_docstrings` Adds ability to configure openapi schema generation to use the route handler docstring for operation description. If `False` docstrings are ignored, this is default behavior for backward compatibility. If `True`, `HTTPRouteHandler.description` takes precedence if set, otherwise the docstring is used. * Adds detail to exception raised during signature model creation. * 1.7.2 * add route map extension * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Correct import * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * fix some issues caused when rebasing Co-authored-by: Zachary Dremann <dremann@gmail.com> Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com> Co-authored-by: Na'aman Hirschfeld <nhirschfeld@gmail.com> Co-authored-by: Dane Solberg <danesolberg@gmail.com> Co-authored-by: Peter Schutt <peter@topsport.com.au> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: josepdaniel <36941460+josepdaniel@users.noreply.github.com> Co-authored-by: Joseph Daniel <jdn@logpoint.com> Co-authored-by: cătălin <catalin@roboces.dev> Co-authored-by: Peter Schutt <peter.github@proton.me> Co-authored-by: Tim Wedde <timwedde@icloud.com> Co-authored-by: Harry <harry.lees@gmail.com>
* add route map extension * change maturin to dev dependency * rust ext: make Node::is_asgi default to false * rust ext: remove unused dependency * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Move rust extension out of starlite folder * Correct import * Include rust source in sdist build * Working extension poetry build * Rename build.py * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * rust ext: remove some uses of `Python::acquire_gil()` * rust ext: don't return `PyResult` for infallible operations * rust ext: hide plain route methods from python interface * rust ext: add route collection parameter to `add_routes` * rust ext: use `IntoPy` trait method for `Node` instead of `as_pydict` * rust ext: refactor parameters for `configure_route_map_node` * rust ext: remove outdated comment * rust_ext: change uses of `cur` to `cur_node` * rust ext: fix typo in route map comments * rust ext: downgrade add_node_to_route_map return value to shared ref * rust_ext: port build_route_middleware_stack into extension util, removing starlite instance dependence * rust ext: add minimal test * Enhancement: Brotli compression middleware (#252) * FEATURE: Added Compression Middleware - Existing Gzip Middleware - Brotli with an optional Gzip fallback. * 1.5.4 * updated pyproject.toml to exclude lines form coverage report * Add tests for `Starlite.construct_route_map` * Address flake8 validation rules * Removes `uuid4()` from within parametrized test cases. Vscode test discovery caches the test case names including parametrized values. This makes having `uuid4()` calls in the parametrized test cases an issue as vscode shows test case failures when it cannot find test cases that it has previously resolved. As the change doesn't affect the utility of the test, it is better to fix the case for vscode users so we don't get the same issue reported in the future. * Addresses cognitive complexity of `DTOFactory.__call__()` by breaking nested logic out into helper methods. Changes no logic, test cov still 100% and existing tests pass. For #203 * updated dependencies * Issue 187 layered parameters (#261) * feat: added parameters to all app layers * feat: refactored handler layer resolution logic * chore: cleanup signature modelling * feat: add layered parameters to kwargs model * fix test coverage * skipped failing test in py 3.7 * update OA params * updated implementation to use ModelField insteam of FieldInfo * add openapi parameter tests * add docs * 1.6.0 * 1.6.1 * Fix route-map path existence test logic (#275) (#277) * added after_response (#279) * added after_response * addressed review comments * Issue 188: resolve exceptions swallowing args (#281) * updated exception init * add tests * 1.6.2 * chore: updated maintainer list (#285) * docs: add cofin as a contributor for maintenance (#286) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Issue #255: allow single element query param in sequence types (#262) * Array handling in query params * Refactor array handling Co-authored-by: Joseph Daniel <jdn@logpoint.com> * docs: add josepdaniel as a contributor for code (#290) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Updates instructions to install `testing` extra. * LifecycleHook improvements. - Adds `LifecycleHook` for eager evaluation of sync vs async callables and centralisation of handler resolution. Generic on handler response. - Adds aliases `AfterRequestHook`, `AfterResponseHook`, `BeforeRequestHook` that are strongly typed to appropriate handler response type. - Adds support for lifecycle hooks that are instance methods by overwriting handlers assigned to class variables on `Controller` only if they are originally functions. Closes #284 * Enhancement: Tortoise-ORM Plugin (#283) * added tortoise to dev dependencies * added base plugin implementation * add tests * updated plugin implementation * cleanup dependencies * updated implementation * fixed issues * resolved issues * add openapi support * fix tests * updated tests * add docs * fix linter issues * updated tests * 1.7.0 * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity (#292) * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity * Make `openapi.create_paramter_for_handler`'s helper functions public * Revise misleading `openapi.get_recursive_handler_parameters` docstrings * Adds `exceptions.utils.create_exception_response()`. - makes `starlite.exceptions` a sub-package with same api as module it replaces. - adds `starlite.exceptions.utils` module to house the response generation helper function. * Supress warning generated from Tortoise ORM DTO test case. Warning: `RuntimeWarning: coroutine 'TortoiseORMPlugin.to_dict' was never awaited` The warning is expected for the underlying code logic and test case, so safe to supress. * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] * Fixes `!!! important` block and adds `<!-- prettier-ignore -->`. * `orjson` use in `WebSocket.{receive,send}_json()` Implementations are functionally the same as upstream except for orjson usage and we raise our own exceptions. Adds tests for `connection.WebSocket`. Creates `tests/connection` and moved `tests/request` to that location. * Support for SwaggerUI (#302) (#303) * Support for SwaggerUI (#302) * Support for SwaggerUI As per #300 * Use built-in copy method * Add basic sanity check tests for ReDoc and Swagger UI routes (#304) Tests for #303 / #302 These tests check whether the UI handlers: - don't throw an Exception - return 200 OK - return HTML of some form * updated urls, add docs * fix memoization issue Co-authored-by: Tim Wedde <timwedde@icloud.com> * 1.7.1 * Allow Partial to annotate fields of nested classes (#288) * Allow Partial to annotate fields for superclasses * added test to ensure __annotations__ are resolved from parent classes * added test for runtime behaviour of Partial on classes that don't inherit from pydantic.BaseModel * use typing.get_type_hints() instead of __annotations__ for getting class type annotations * raise ImproperlyConfiguredException if class passed to Partial doesn't inherit from BaseModel * added test to ensure Partial raises ImproperlyConfiguredException if an invalid class is given * added Partial section to DTO docs * docs: add Harry-Lees as a contributor for code, doc (#305) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * update docs * Tidy grammar in comment. * `OpenAPIConfig.use_handler_docstrings` Adds ability to configure openapi schema generation to use the route handler docstring for operation description. If `False` docstrings are ignored, this is default behavior for backward compatibility. If `True`, `HTTPRouteHandler.description` takes precedence if set, otherwise the docstring is used. * Adds detail to exception raised during signature model creation. * 1.7.2 * add route map extension * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Correct import * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * fix some issues caused when rebasing Co-authored-by: Zachary Dremann <dremann@gmail.com> Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com> Co-authored-by: Na'aman Hirschfeld <nhirschfeld@gmail.com> Co-authored-by: Dane Solberg <danesolberg@gmail.com> Co-authored-by: Peter Schutt <peter@topsport.com.au> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: josepdaniel <36941460+josepdaniel@users.noreply.github.com> Co-authored-by: Joseph Daniel <jdn@logpoint.com> Co-authored-by: cătălin <catalin@roboces.dev> Co-authored-by: Peter Schutt <peter.github@proton.me> Co-authored-by: Tim Wedde <timwedde@icloud.com> Co-authored-by: Harry <harry.lees@gmail.com> Fix issues with Rust route map bindings (#310) * fix poetry.lock error * put auto-initialize behind a feature flag * update poetry.lock * add back missing plain_routes attribute (will be removed) cleanup Misc rust fixes/changes (#312) * Expose RouteMap as a python stub * Remove unused duplicate of rust extension inside starlite dir * Rename module to just `route_map` It's not clear that we need the module to include `_rs` * Remove need for macro for get_attr_and_downcast * Replace macro with a lambda * Use entry.or_insert_with for getting/inserting nodes Should be slightly more efficent: We only have to look up once, rather than twice * Remove unneeded `.into()`/`to_object()` calls * Add back a comment to the top of the route_map type stubs Explain what the file is, and where the implementation is located Update rust setup (#314) * updated folder structure and add pre commit hooks * replace pyi file with py file * update codespell hook * turn off TC006 * update ci Rust Bindings: CI (#317) * updated ci to handle rust testing * update python path * fix coverage * addressed review comments * remove flag preventing install when deps are cached Rust bindings - Some unit tests (#319) * update poetry.lock * add some init tests * add doc comment for gett_attr_and_downcast * derive Default for Node * reformat python scripts for rust tests
* add route map extension * change maturin to dev dependency * rust ext: make Node::is_asgi default to false * rust ext: remove unused dependency * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Move rust extension out of starlite folder * Correct import * Include rust source in sdist build * Working extension poetry build * Rename build.py * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * rust ext: remove some uses of `Python::acquire_gil()` * rust ext: don't return `PyResult` for infallible operations * rust ext: hide plain route methods from python interface * rust ext: add route collection parameter to `add_routes` * rust ext: use `IntoPy` trait method for `Node` instead of `as_pydict` * rust ext: refactor parameters for `configure_route_map_node` * rust ext: remove outdated comment * rust_ext: change uses of `cur` to `cur_node` * rust ext: fix typo in route map comments * rust ext: downgrade add_node_to_route_map return value to shared ref * rust_ext: port build_route_middleware_stack into extension util, removing starlite instance dependence * rust ext: add minimal test * Enhancement: Brotli compression middleware (#252) * FEATURE: Added Compression Middleware - Existing Gzip Middleware - Brotli with an optional Gzip fallback. * 1.5.4 * updated pyproject.toml to exclude lines form coverage report * Add tests for `Starlite.construct_route_map` * Address flake8 validation rules * Removes `uuid4()` from within parametrized test cases. Vscode test discovery caches the test case names including parametrized values. This makes having `uuid4()` calls in the parametrized test cases an issue as vscode shows test case failures when it cannot find test cases that it has previously resolved. As the change doesn't affect the utility of the test, it is better to fix the case for vscode users so we don't get the same issue reported in the future. * Addresses cognitive complexity of `DTOFactory.__call__()` by breaking nested logic out into helper methods. Changes no logic, test cov still 100% and existing tests pass. For #203 * updated dependencies * Issue 187 layered parameters (#261) * feat: added parameters to all app layers * feat: refactored handler layer resolution logic * chore: cleanup signature modelling * feat: add layered parameters to kwargs model * fix test coverage * skipped failing test in py 3.7 * update OA params * updated implementation to use ModelField insteam of FieldInfo * add openapi parameter tests * add docs * 1.6.0 * 1.6.1 * Fix route-map path existence test logic (#275) (#277) * added after_response (#279) * added after_response * addressed review comments * Issue 188: resolve exceptions swallowing args (#281) * updated exception init * add tests * 1.6.2 * chore: updated maintainer list (#285) * docs: add cofin as a contributor for maintenance (#286) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Issue #255: allow single element query param in sequence types (#262) * Array handling in query params * Refactor array handling Co-authored-by: Joseph Daniel <jdn@logpoint.com> * docs: add josepdaniel as a contributor for code (#290) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Updates instructions to install `testing` extra. * LifecycleHook improvements. - Adds `LifecycleHook` for eager evaluation of sync vs async callables and centralisation of handler resolution. Generic on handler response. - Adds aliases `AfterRequestHook`, `AfterResponseHook`, `BeforeRequestHook` that are strongly typed to appropriate handler response type. - Adds support for lifecycle hooks that are instance methods by overwriting handlers assigned to class variables on `Controller` only if they are originally functions. Closes #284 * Enhancement: Tortoise-ORM Plugin (#283) * added tortoise to dev dependencies * added base plugin implementation * add tests * updated plugin implementation * cleanup dependencies * updated implementation * fixed issues * resolved issues * add openapi support * fix tests * updated tests * add docs * fix linter issues * updated tests * 1.7.0 * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity (#292) * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity * Make `openapi.create_paramter_for_handler`'s helper functions public * Revise misleading `openapi.get_recursive_handler_parameters` docstrings * Adds `exceptions.utils.create_exception_response()`. - makes `starlite.exceptions` a sub-package with same api as module it replaces. - adds `starlite.exceptions.utils` module to house the response generation helper function. * Supress warning generated from Tortoise ORM DTO test case. Warning: `RuntimeWarning: coroutine 'TortoiseORMPlugin.to_dict' was never awaited` The warning is expected for the underlying code logic and test case, so safe to supress. * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] * Fixes `!!! important` block and adds `<!-- prettier-ignore -->`. * `orjson` use in `WebSocket.{receive,send}_json()` Implementations are functionally the same as upstream except for orjson usage and we raise our own exceptions. Adds tests for `connection.WebSocket`. Creates `tests/connection` and moved `tests/request` to that location. * Support for SwaggerUI (#302) (#303) * Support for SwaggerUI (#302) * Support for SwaggerUI As per #300 * Use built-in copy method * Add basic sanity check tests for ReDoc and Swagger UI routes (#304) Tests for #303 / #302 These tests check whether the UI handlers: - don't throw an Exception - return 200 OK - return HTML of some form * updated urls, add docs * fix memoization issue Co-authored-by: Tim Wedde <timwedde@icloud.com> * 1.7.1 * Allow Partial to annotate fields of nested classes (#288) * Allow Partial to annotate fields for superclasses * added test to ensure __annotations__ are resolved from parent classes * added test for runtime behaviour of Partial on classes that don't inherit from pydantic.BaseModel * use typing.get_type_hints() instead of __annotations__ for getting class type annotations * raise ImproperlyConfiguredException if class passed to Partial doesn't inherit from BaseModel * added test to ensure Partial raises ImproperlyConfiguredException if an invalid class is given * added Partial section to DTO docs * docs: add Harry-Lees as a contributor for code, doc (#305) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * update docs * Tidy grammar in comment. * `OpenAPIConfig.use_handler_docstrings` Adds ability to configure openapi schema generation to use the route handler docstring for operation description. If `False` docstrings are ignored, this is default behavior for backward compatibility. If `True`, `HTTPRouteHandler.description` takes precedence if set, otherwise the docstring is used. * Adds detail to exception raised during signature model creation. * 1.7.2 * add route map extension * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Correct import * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * fix some issues caused when rebasing Co-authored-by: Zachary Dremann <dremann@gmail.com> Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com> Co-authored-by: Na'aman Hirschfeld <nhirschfeld@gmail.com> Co-authored-by: Dane Solberg <danesolberg@gmail.com> Co-authored-by: Peter Schutt <peter@topsport.com.au> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: josepdaniel <36941460+josepdaniel@users.noreply.github.com> Co-authored-by: Joseph Daniel <jdn@logpoint.com> Co-authored-by: cătălin <catalin@roboces.dev> Co-authored-by: Peter Schutt <peter.github@proton.me> Co-authored-by: Tim Wedde <timwedde@icloud.com> Co-authored-by: Harry <harry.lees@gmail.com> Fix issues with Rust route map bindings (#310) * fix poetry.lock error * put auto-initialize behind a feature flag * update poetry.lock * add back missing plain_routes attribute (will be removed) cleanup Misc rust fixes/changes (#312) * Expose RouteMap as a python stub * Remove unused duplicate of rust extension inside starlite dir * Rename module to just `route_map` It's not clear that we need the module to include `_rs` * Remove need for macro for get_attr_and_downcast * Replace macro with a lambda * Use entry.or_insert_with for getting/inserting nodes Should be slightly more efficent: We only have to look up once, rather than twice * Remove unneeded `.into()`/`to_object()` calls * Add back a comment to the top of the route_map type stubs Explain what the file is, and where the implementation is located Update rust setup (#314) * updated folder structure and add pre commit hooks * replace pyi file with py file * update codespell hook * turn off TC006 * update ci Rust Bindings: CI (#317) * updated ci to handle rust testing * update python path * fix coverage * addressed review comments * remove flag preventing install when deps are cached Rust bindings - Some unit tests (#319) * update poetry.lock * add some init tests * add doc comment for gett_attr_and_downcast * derive Default for Node * reformat python scripts for rust tests
* add route map extension * change maturin to dev dependency * rust ext: make Node::is_asgi default to false * rust ext: remove unused dependency * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Move rust extension out of starlite folder * Correct import * Include rust source in sdist build * Working extension poetry build * Rename build.py * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * rust ext: remove some uses of `Python::acquire_gil()` * rust ext: don't return `PyResult` for infallible operations * rust ext: hide plain route methods from python interface * rust ext: add route collection parameter to `add_routes` * rust ext: use `IntoPy` trait method for `Node` instead of `as_pydict` * rust ext: refactor parameters for `configure_route_map_node` * rust ext: remove outdated comment * rust_ext: change uses of `cur` to `cur_node` * rust ext: fix typo in route map comments * rust ext: downgrade add_node_to_route_map return value to shared ref * rust_ext: port build_route_middleware_stack into extension util, removing starlite instance dependence * rust ext: add minimal test * Enhancement: Brotli compression middleware (#252) * FEATURE: Added Compression Middleware - Existing Gzip Middleware - Brotli with an optional Gzip fallback. * 1.5.4 * updated pyproject.toml to exclude lines form coverage report * Add tests for `Starlite.construct_route_map` * Address flake8 validation rules * Removes `uuid4()` from within parametrized test cases. Vscode test discovery caches the test case names including parametrized values. This makes having `uuid4()` calls in the parametrized test cases an issue as vscode shows test case failures when it cannot find test cases that it has previously resolved. As the change doesn't affect the utility of the test, it is better to fix the case for vscode users so we don't get the same issue reported in the future. * Addresses cognitive complexity of `DTOFactory.__call__()` by breaking nested logic out into helper methods. Changes no logic, test cov still 100% and existing tests pass. For #203 * updated dependencies * Issue 187 layered parameters (#261) * feat: added parameters to all app layers * feat: refactored handler layer resolution logic * chore: cleanup signature modelling * feat: add layered parameters to kwargs model * fix test coverage * skipped failing test in py 3.7 * update OA params * updated implementation to use ModelField insteam of FieldInfo * add openapi parameter tests * add docs * 1.6.0 * 1.6.1 * Fix route-map path existence test logic (#275) (#277) * added after_response (#279) * added after_response * addressed review comments * Issue 188: resolve exceptions swallowing args (#281) * updated exception init * add tests * 1.6.2 * chore: updated maintainer list (#285) * docs: add cofin as a contributor for maintenance (#286) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Issue #255: allow single element query param in sequence types (#262) * Array handling in query params * Refactor array handling Co-authored-by: Joseph Daniel <jdn@logpoint.com> * docs: add josepdaniel as a contributor for code (#290) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Updates instructions to install `testing` extra. * LifecycleHook improvements. - Adds `LifecycleHook` for eager evaluation of sync vs async callables and centralisation of handler resolution. Generic on handler response. - Adds aliases `AfterRequestHook`, `AfterResponseHook`, `BeforeRequestHook` that are strongly typed to appropriate handler response type. - Adds support for lifecycle hooks that are instance methods by overwriting handlers assigned to class variables on `Controller` only if they are originally functions. Closes #284 * Enhancement: Tortoise-ORM Plugin (#283) * added tortoise to dev dependencies * added base plugin implementation * add tests * updated plugin implementation * cleanup dependencies * updated implementation * fixed issues * resolved issues * add openapi support * fix tests * updated tests * add docs * fix linter issues * updated tests * 1.7.0 * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity (#292) * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity * Make `openapi.create_paramter_for_handler`'s helper functions public * Revise misleading `openapi.get_recursive_handler_parameters` docstrings * Adds `exceptions.utils.create_exception_response()`. - makes `starlite.exceptions` a sub-package with same api as module it replaces. - adds `starlite.exceptions.utils` module to house the response generation helper function. * Supress warning generated from Tortoise ORM DTO test case. Warning: `RuntimeWarning: coroutine 'TortoiseORMPlugin.to_dict' was never awaited` The warning is expected for the underlying code logic and test case, so safe to supress. * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] * Fixes `!!! important` block and adds `<!-- prettier-ignore -->`. * `orjson` use in `WebSocket.{receive,send}_json()` Implementations are functionally the same as upstream except for orjson usage and we raise our own exceptions. Adds tests for `connection.WebSocket`. Creates `tests/connection` and moved `tests/request` to that location. * Support for SwaggerUI (#302) (#303) * Support for SwaggerUI (#302) * Support for SwaggerUI As per #300 * Use built-in copy method * Add basic sanity check tests for ReDoc and Swagger UI routes (#304) Tests for #303 / #302 These tests check whether the UI handlers: - don't throw an Exception - return 200 OK - return HTML of some form * updated urls, add docs * fix memoization issue Co-authored-by: Tim Wedde <timwedde@icloud.com> * 1.7.1 * Allow Partial to annotate fields of nested classes (#288) * Allow Partial to annotate fields for superclasses * added test to ensure __annotations__ are resolved from parent classes * added test for runtime behaviour of Partial on classes that don't inherit from pydantic.BaseModel * use typing.get_type_hints() instead of __annotations__ for getting class type annotations * raise ImproperlyConfiguredException if class passed to Partial doesn't inherit from BaseModel * added test to ensure Partial raises ImproperlyConfiguredException if an invalid class is given * added Partial section to DTO docs * docs: add Harry-Lees as a contributor for code, doc (#305) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * update docs * Tidy grammar in comment. * `OpenAPIConfig.use_handler_docstrings` Adds ability to configure openapi schema generation to use the route handler docstring for operation description. If `False` docstrings are ignored, this is default behavior for backward compatibility. If `True`, `HTTPRouteHandler.description` takes precedence if set, otherwise the docstring is used. * Adds detail to exception raised during signature model creation. * 1.7.2 * add route map extension * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Correct import * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * fix some issues caused when rebasing Co-authored-by: Zachary Dremann <dremann@gmail.com> Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com> Co-authored-by: Na'aman Hirschfeld <nhirschfeld@gmail.com> Co-authored-by: Dane Solberg <danesolberg@gmail.com> Co-authored-by: Peter Schutt <peter@topsport.com.au> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: josepdaniel <36941460+josepdaniel@users.noreply.github.com> Co-authored-by: Joseph Daniel <jdn@logpoint.com> Co-authored-by: cătălin <catalin@roboces.dev> Co-authored-by: Peter Schutt <peter.github@proton.me> Co-authored-by: Tim Wedde <timwedde@icloud.com> Co-authored-by: Harry <harry.lees@gmail.com> Fix issues with Rust route map bindings (#310) * fix poetry.lock error * put auto-initialize behind a feature flag * update poetry.lock * add back missing plain_routes attribute (will be removed) cleanup Misc rust fixes/changes (#312) * Expose RouteMap as a python stub * Remove unused duplicate of rust extension inside starlite dir * Rename module to just `route_map` It's not clear that we need the module to include `_rs` * Remove need for macro for get_attr_and_downcast * Replace macro with a lambda * Use entry.or_insert_with for getting/inserting nodes Should be slightly more efficent: We only have to look up once, rather than twice * Remove unneeded `.into()`/`to_object()` calls * Add back a comment to the top of the route_map type stubs Explain what the file is, and where the implementation is located Update rust setup (#314) * updated folder structure and add pre commit hooks * replace pyi file with py file * update codespell hook * turn off TC006 * update ci Rust Bindings: CI (#317) * updated ci to handle rust testing * update python path * fix coverage * addressed review comments * remove flag preventing install when deps are cached Rust bindings - Some unit tests (#319) * update poetry.lock * add some init tests * add doc comment for gett_attr_and_downcast * derive Default for Node * reformat python scripts for rust tests
…ngs (litestar-org#270) * add route map extension * change maturin to dev dependency * rust ext: make Node::is_asgi default to false * rust ext: remove unused dependency * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Move rust extension out of starlite folder * Correct import * Include rust source in sdist build * Working extension poetry build * Rename build.py * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * rust ext: remove some uses of `Python::acquire_gil()` * rust ext: don't return `PyResult` for infallible operations * rust ext: hide plain route methods from python interface * rust ext: add route collection parameter to `add_routes` * rust ext: use `IntoPy` trait method for `Node` instead of `as_pydict` * rust ext: refactor parameters for `configure_route_map_node` * rust ext: remove outdated comment * rust_ext: change uses of `cur` to `cur_node` * rust ext: fix typo in route map comments * rust ext: downgrade add_node_to_route_map return value to shared ref * rust_ext: port build_route_middleware_stack into extension util, removing starlite instance dependence * rust ext: add minimal test * Enhancement: Brotli compression middleware (litestar-org#252) * FEATURE: Added Compression Middleware - Existing Gzip Middleware - Brotli with an optional Gzip fallback. * 1.5.4 * updated pyproject.toml to exclude lines form coverage report * Add tests for `Starlite.construct_route_map` * Address flake8 validation rules * Removes `uuid4()` from within parametrized test cases. Vscode test discovery caches the test case names including parametrized values. This makes having `uuid4()` calls in the parametrized test cases an issue as vscode shows test case failures when it cannot find test cases that it has previously resolved. As the change doesn't affect the utility of the test, it is better to fix the case for vscode users so we don't get the same issue reported in the future. * Addresses cognitive complexity of `DTOFactory.__call__()` by breaking nested logic out into helper methods. Changes no logic, test cov still 100% and existing tests pass. For litestar-org#203 * updated dependencies * Issue 187 layered parameters (litestar-org#261) * feat: added parameters to all app layers * feat: refactored handler layer resolution logic * chore: cleanup signature modelling * feat: add layered parameters to kwargs model * fix test coverage * skipped failing test in py 3.7 * update OA params * updated implementation to use ModelField insteam of FieldInfo * add openapi parameter tests * add docs * 1.6.0 * 1.6.1 * Fix route-map path existence test logic (litestar-org#275) (litestar-org#277) * added after_response (litestar-org#279) * added after_response * addressed review comments * Issue 188: resolve exceptions swallowing args (litestar-org#281) * updated exception init * add tests * 1.6.2 * chore: updated maintainer list (litestar-org#285) * docs: add cofin as a contributor for maintenance (litestar-org#286) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Issue litestar-org#255: allow single element query param in sequence types (litestar-org#262) * Array handling in query params * Refactor array handling Co-authored-by: Joseph Daniel <jdn@logpoint.com> * docs: add josepdaniel as a contributor for code (litestar-org#290) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Updates instructions to install `testing` extra. * LifecycleHook improvements. - Adds `LifecycleHook` for eager evaluation of sync vs async callables and centralisation of handler resolution. Generic on handler response. - Adds aliases `AfterRequestHook`, `AfterResponseHook`, `BeforeRequestHook` that are strongly typed to appropriate handler response type. - Adds support for lifecycle hooks that are instance methods by overwriting handlers assigned to class variables on `Controller` only if they are originally functions. Closes litestar-org#284 * Enhancement: Tortoise-ORM Plugin (litestar-org#283) * added tortoise to dev dependencies * added base plugin implementation * add tests * updated plugin implementation * cleanup dependencies * updated implementation * fixed issues * resolved issues * add openapi support * fix tests * updated tests * add docs * fix linter issues * updated tests * 1.7.0 * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity (litestar-org#292) * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity * Make `openapi.create_paramter_for_handler`'s helper functions public * Revise misleading `openapi.get_recursive_handler_parameters` docstrings * Adds `exceptions.utils.create_exception_response()`. - makes `starlite.exceptions` a sub-package with same api as module it replaces. - adds `starlite.exceptions.utils` module to house the response generation helper function. * Supress warning generated from Tortoise ORM DTO test case. Warning: `RuntimeWarning: coroutine 'TortoiseORMPlugin.to_dict' was never awaited` The warning is expected for the underlying code logic and test case, so safe to supress. * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] * Fixes `!!! important` block and adds `<!-- prettier-ignore -->`. * `orjson` use in `WebSocket.{receive,send}_json()` Implementations are functionally the same as upstream except for orjson usage and we raise our own exceptions. Adds tests for `connection.WebSocket`. Creates `tests/connection` and moved `tests/request` to that location. * Support for SwaggerUI (litestar-org#302) (litestar-org#303) * Support for SwaggerUI (litestar-org#302) * Support for SwaggerUI As per litestar-org#300 * Use built-in copy method * Add basic sanity check tests for ReDoc and Swagger UI routes (litestar-org#304) Tests for litestar-org#303 / litestar-org#302 These tests check whether the UI handlers: - don't throw an Exception - return 200 OK - return HTML of some form * updated urls, add docs * fix memoization issue Co-authored-by: Tim Wedde <timwedde@icloud.com> * 1.7.1 * Allow Partial to annotate fields of nested classes (litestar-org#288) * Allow Partial to annotate fields for superclasses * added test to ensure __annotations__ are resolved from parent classes * added test for runtime behaviour of Partial on classes that don't inherit from pydantic.BaseModel * use typing.get_type_hints() instead of __annotations__ for getting class type annotations * raise ImproperlyConfiguredException if class passed to Partial doesn't inherit from BaseModel * added test to ensure Partial raises ImproperlyConfiguredException if an invalid class is given * added Partial section to DTO docs * docs: add Harry-Lees as a contributor for code, doc (litestar-org#305) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * update docs * Tidy grammar in comment. * `OpenAPIConfig.use_handler_docstrings` Adds ability to configure openapi schema generation to use the route handler docstring for operation description. If `False` docstrings are ignored, this is default behavior for backward compatibility. If `True`, `HTTPRouteHandler.description` takes precedence if set, otherwise the docstring is used. * Adds detail to exception raised during signature model creation. * 1.7.2 * add route map extension * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Correct import * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * fix some issues caused when rebasing Co-authored-by: Zachary Dremann <dremann@gmail.com> Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com> Co-authored-by: Na'aman Hirschfeld <nhirschfeld@gmail.com> Co-authored-by: Dane Solberg <danesolberg@gmail.com> Co-authored-by: Peter Schutt <peter@topsport.com.au> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: josepdaniel <36941460+josepdaniel@users.noreply.github.com> Co-authored-by: Joseph Daniel <jdn@logpoint.com> Co-authored-by: cătălin <catalin@roboces.dev> Co-authored-by: Peter Schutt <peter.github@proton.me> Co-authored-by: Tim Wedde <timwedde@icloud.com> Co-authored-by: Harry <harry.lees@gmail.com> Fix issues with Rust route map bindings (litestar-org#310) * fix poetry.lock error * put auto-initialize behind a feature flag * update poetry.lock * add back missing plain_routes attribute (will be removed) cleanup Misc rust fixes/changes (litestar-org#312) * Expose RouteMap as a python stub * Remove unused duplicate of rust extension inside starlite dir * Rename module to just `route_map` It's not clear that we need the module to include `_rs` * Remove need for macro for get_attr_and_downcast * Replace macro with a lambda * Use entry.or_insert_with for getting/inserting nodes Should be slightly more efficent: We only have to look up once, rather than twice * Remove unneeded `.into()`/`to_object()` calls * Add back a comment to the top of the route_map type stubs Explain what the file is, and where the implementation is located Update rust setup (litestar-org#314) * updated folder structure and add pre commit hooks * replace pyi file with py file * update codespell hook * turn off TC006 * update ci Rust Bindings: CI (litestar-org#317) * updated ci to handle rust testing * update python path * fix coverage * addressed review comments * remove flag preventing install when deps are cached Rust bindings - Some unit tests (litestar-org#319) * update poetry.lock * add some init tests * add doc comment for gett_attr_and_downcast * derive Default for Node * reformat python scripts for rust tests
* Issue #177: Add a baseline for Rust path resolution bindings (#270) * add route map extension * change maturin to dev dependency * rust ext: make Node::is_asgi default to false * rust ext: remove unused dependency * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Move rust extension out of starlite folder * Correct import * Include rust source in sdist build * Working extension poetry build * Rename build.py * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * rust ext: remove some uses of `Python::acquire_gil()` * rust ext: don't return `PyResult` for infallible operations * rust ext: hide plain route methods from python interface * rust ext: add route collection parameter to `add_routes` * rust ext: use `IntoPy` trait method for `Node` instead of `as_pydict` * rust ext: refactor parameters for `configure_route_map_node` * rust ext: remove outdated comment * rust_ext: change uses of `cur` to `cur_node` * rust ext: fix typo in route map comments * rust ext: downgrade add_node_to_route_map return value to shared ref * rust_ext: port build_route_middleware_stack into extension util, removing starlite instance dependence * rust ext: add minimal test * Enhancement: Brotli compression middleware (#252) * FEATURE: Added Compression Middleware - Existing Gzip Middleware - Brotli with an optional Gzip fallback. * 1.5.4 * updated pyproject.toml to exclude lines form coverage report * Add tests for `Starlite.construct_route_map` * Address flake8 validation rules * Removes `uuid4()` from within parametrized test cases. Vscode test discovery caches the test case names including parametrized values. This makes having `uuid4()` calls in the parametrized test cases an issue as vscode shows test case failures when it cannot find test cases that it has previously resolved. As the change doesn't affect the utility of the test, it is better to fix the case for vscode users so we don't get the same issue reported in the future. * Addresses cognitive complexity of `DTOFactory.__call__()` by breaking nested logic out into helper methods. Changes no logic, test cov still 100% and existing tests pass. For #203 * updated dependencies * Issue 187 layered parameters (#261) * feat: added parameters to all app layers * feat: refactored handler layer resolution logic * chore: cleanup signature modelling * feat: add layered parameters to kwargs model * fix test coverage * skipped failing test in py 3.7 * update OA params * updated implementation to use ModelField insteam of FieldInfo * add openapi parameter tests * add docs * 1.6.0 * 1.6.1 * Fix route-map path existence test logic (#275) (#277) * added after_response (#279) * added after_response * addressed review comments * Issue 188: resolve exceptions swallowing args (#281) * updated exception init * add tests * 1.6.2 * chore: updated maintainer list (#285) * docs: add cofin as a contributor for maintenance (#286) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Issue #255: allow single element query param in sequence types (#262) * Array handling in query params * Refactor array handling Co-authored-by: Joseph Daniel <jdn@logpoint.com> * docs: add josepdaniel as a contributor for code (#290) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Updates instructions to install `testing` extra. * LifecycleHook improvements. - Adds `LifecycleHook` for eager evaluation of sync vs async callables and centralisation of handler resolution. Generic on handler response. - Adds aliases `AfterRequestHook`, `AfterResponseHook`, `BeforeRequestHook` that are strongly typed to appropriate handler response type. - Adds support for lifecycle hooks that are instance methods by overwriting handlers assigned to class variables on `Controller` only if they are originally functions. Closes #284 * Enhancement: Tortoise-ORM Plugin (#283) * added tortoise to dev dependencies * added base plugin implementation * add tests * updated plugin implementation * cleanup dependencies * updated implementation * fixed issues * resolved issues * add openapi support * fix tests * updated tests * add docs * fix linter issues * updated tests * 1.7.0 * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity (#292) * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity * Make `openapi.create_paramter_for_handler`'s helper functions public * Revise misleading `openapi.get_recursive_handler_parameters` docstrings * Adds `exceptions.utils.create_exception_response()`. - makes `starlite.exceptions` a sub-package with same api as module it replaces. - adds `starlite.exceptions.utils` module to house the response generation helper function. * Supress warning generated from Tortoise ORM DTO test case. Warning: `RuntimeWarning: coroutine 'TortoiseORMPlugin.to_dict' was never awaited` The warning is expected for the underlying code logic and test case, so safe to supress. * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] * Fixes `!!! important` block and adds `<!-- prettier-ignore -->`. * `orjson` use in `WebSocket.{receive,send}_json()` Implementations are functionally the same as upstream except for orjson usage and we raise our own exceptions. Adds tests for `connection.WebSocket`. Creates `tests/connection` and moved `tests/request` to that location. * Support for SwaggerUI (#302) (#303) * Support for SwaggerUI (#302) * Support for SwaggerUI As per #300 * Use built-in copy method * Add basic sanity check tests for ReDoc and Swagger UI routes (#304) Tests for #303 / #302 These tests check whether the UI handlers: - don't throw an Exception - return 200 OK - return HTML of some form * updated urls, add docs * fix memoization issue Co-authored-by: Tim Wedde <timwedde@icloud.com> * 1.7.1 * Allow Partial to annotate fields of nested classes (#288) * Allow Partial to annotate fields for superclasses * added test to ensure __annotations__ are resolved from parent classes * added test for runtime behaviour of Partial on classes that don't inherit from pydantic.BaseModel * use typing.get_type_hints() instead of __annotations__ for getting class type annotations * raise ImproperlyConfiguredException if class passed to Partial doesn't inherit from BaseModel * added test to ensure Partial raises ImproperlyConfiguredException if an invalid class is given * added Partial section to DTO docs * docs: add Harry-Lees as a contributor for code, doc (#305) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * update docs * Tidy grammar in comment. * `OpenAPIConfig.use_handler_docstrings` Adds ability to configure openapi schema generation to use the route handler docstring for operation description. If `False` docstrings are ignored, this is default behavior for backward compatibility. If `True`, `HTTPRouteHandler.description` takes precedence if set, otherwise the docstring is used. * Adds detail to exception raised during signature model creation. * 1.7.2 * add route map extension * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Correct import * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * fix some issues caused when rebasing Co-authored-by: Zachary Dremann <dremann@gmail.com> Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com> Co-authored-by: Na'aman Hirschfeld <nhirschfeld@gmail.com> Co-authored-by: Dane Solberg <danesolberg@gmail.com> Co-authored-by: Peter Schutt <peter@topsport.com.au> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: josepdaniel <36941460+josepdaniel@users.noreply.github.com> Co-authored-by: Joseph Daniel <jdn@logpoint.com> Co-authored-by: cătălin <catalin@roboces.dev> Co-authored-by: Peter Schutt <peter.github@proton.me> Co-authored-by: Tim Wedde <timwedde@icloud.com> Co-authored-by: Harry <harry.lees@gmail.com> Fix issues with Rust route map bindings (#310) * fix poetry.lock error * put auto-initialize behind a feature flag * update poetry.lock * add back missing plain_routes attribute (will be removed) cleanup Misc rust fixes/changes (#312) * Expose RouteMap as a python stub * Remove unused duplicate of rust extension inside starlite dir * Rename module to just `route_map` It's not clear that we need the module to include `_rs` * Remove need for macro for get_attr_and_downcast * Replace macro with a lambda * Use entry.or_insert_with for getting/inserting nodes Should be slightly more efficent: We only have to look up once, rather than twice * Remove unneeded `.into()`/`to_object()` calls * Add back a comment to the top of the route_map type stubs Explain what the file is, and where the implementation is located Update rust setup (#314) * updated folder structure and add pre commit hooks * replace pyi file with py file * update codespell hook * turn off TC006 * update ci Rust Bindings: CI (#317) * updated ci to handle rust testing * update python path * fix coverage * addressed review comments * remove flag preventing install when deps are cached Rust bindings - Some unit tests (#319) * update poetry.lock * add some init tests * add doc comment for gett_attr_and_downcast * derive Default for Node * reformat python scripts for rust tests * First simple routing unit test * Import less of starlite The unit tests for the route_map extension should not need to (transitively) import starlite.route_map * Fix unit tests after rebase * Simplify creation of routes * Avoid stack overflow on drop * Heavily refactor rust code * Convert HandlerGroup to an enum * Include cargo files in sdist * Address comments * Fix pytests added around static handlers * Comment out slotscheck Co-authored-by: Nicholas Ramos <35410160+nramos0@users.noreply.github.com>
* Issue #177: Add a baseline for Rust path resolution bindings (#270) * add route map extension * change maturin to dev dependency * rust ext: make Node::is_asgi default to false * rust ext: remove unused dependency * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Move rust extension out of starlite folder * Correct import * Include rust source in sdist build * Working extension poetry build * Rename build.py * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * rust ext: remove some uses of `Python::acquire_gil()` * rust ext: don't return `PyResult` for infallible operations * rust ext: hide plain route methods from python interface * rust ext: add route collection parameter to `add_routes` * rust ext: use `IntoPy` trait method for `Node` instead of `as_pydict` * rust ext: refactor parameters for `configure_route_map_node` * rust ext: remove outdated comment * rust_ext: change uses of `cur` to `cur_node` * rust ext: fix typo in route map comments * rust ext: downgrade add_node_to_route_map return value to shared ref * rust_ext: port build_route_middleware_stack into extension util, removing starlite instance dependence * rust ext: add minimal test * Enhancement: Brotli compression middleware (#252) * FEATURE: Added Compression Middleware - Existing Gzip Middleware - Brotli with an optional Gzip fallback. * 1.5.4 * updated pyproject.toml to exclude lines form coverage report * Add tests for `Starlite.construct_route_map` * Address flake8 validation rules * Removes `uuid4()` from within parametrized test cases. Vscode test discovery caches the test case names including parametrized values. This makes having `uuid4()` calls in the parametrized test cases an issue as vscode shows test case failures when it cannot find test cases that it has previously resolved. As the change doesn't affect the utility of the test, it is better to fix the case for vscode users so we don't get the same issue reported in the future. * Addresses cognitive complexity of `DTOFactory.__call__()` by breaking nested logic out into helper methods. Changes no logic, test cov still 100% and existing tests pass. For #203 * updated dependencies * Issue 187 layered parameters (#261) * feat: added parameters to all app layers * feat: refactored handler layer resolution logic * chore: cleanup signature modelling * feat: add layered parameters to kwargs model * fix test coverage * skipped failing test in py 3.7 * update OA params * updated implementation to use ModelField insteam of FieldInfo * add openapi parameter tests * add docs * 1.6.0 * 1.6.1 * Fix route-map path existence test logic (#275) (#277) * added after_response (#279) * added after_response * addressed review comments * Issue 188: resolve exceptions swallowing args (#281) * updated exception init * add tests * 1.6.2 * chore: updated maintainer list (#285) * docs: add cofin as a contributor for maintenance (#286) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Issue #255: allow single element query param in sequence types (#262) * Array handling in query params * Refactor array handling Co-authored-by: Joseph Daniel <jdn@logpoint.com> * docs: add josepdaniel as a contributor for code (#290) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Updates instructions to install `testing` extra. * LifecycleHook improvements. - Adds `LifecycleHook` for eager evaluation of sync vs async callables and centralisation of handler resolution. Generic on handler response. - Adds aliases `AfterRequestHook`, `AfterResponseHook`, `BeforeRequestHook` that are strongly typed to appropriate handler response type. - Adds support for lifecycle hooks that are instance methods by overwriting handlers assigned to class variables on `Controller` only if they are originally functions. Closes #284 * Enhancement: Tortoise-ORM Plugin (#283) * added tortoise to dev dependencies * added base plugin implementation * add tests * updated plugin implementation * cleanup dependencies * updated implementation * fixed issues * resolved issues * add openapi support * fix tests * updated tests * add docs * fix linter issues * updated tests * 1.7.0 * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity (#292) * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity * Make `openapi.create_paramter_for_handler`'s helper functions public * Revise misleading `openapi.get_recursive_handler_parameters` docstrings * Adds `exceptions.utils.create_exception_response()`. - makes `starlite.exceptions` a sub-package with same api as module it replaces. - adds `starlite.exceptions.utils` module to house the response generation helper function. * Supress warning generated from Tortoise ORM DTO test case. Warning: `RuntimeWarning: coroutine 'TortoiseORMPlugin.to_dict' was never awaited` The warning is expected for the underlying code logic and test case, so safe to supress. * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] * Fixes `!!! important` block and adds `<!-- prettier-ignore -->`. * `orjson` use in `WebSocket.{receive,send}_json()` Implementations are functionally the same as upstream except for orjson usage and we raise our own exceptions. Adds tests for `connection.WebSocket`. Creates `tests/connection` and moved `tests/request` to that location. * Support for SwaggerUI (#302) (#303) * Support for SwaggerUI (#302) * Support for SwaggerUI As per #300 * Use built-in copy method * Add basic sanity check tests for ReDoc and Swagger UI routes (#304) Tests for #303 / #302 These tests check whether the UI handlers: - don't throw an Exception - return 200 OK - return HTML of some form * updated urls, add docs * fix memoization issue Co-authored-by: Tim Wedde <timwedde@icloud.com> * 1.7.1 * Allow Partial to annotate fields of nested classes (#288) * Allow Partial to annotate fields for superclasses * added test to ensure __annotations__ are resolved from parent classes * added test for runtime behaviour of Partial on classes that don't inherit from pydantic.BaseModel * use typing.get_type_hints() instead of __annotations__ for getting class type annotations * raise ImproperlyConfiguredException if class passed to Partial doesn't inherit from BaseModel * added test to ensure Partial raises ImproperlyConfiguredException if an invalid class is given * added Partial section to DTO docs * docs: add Harry-Lees as a contributor for code, doc (#305) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * update docs * Tidy grammar in comment. * `OpenAPIConfig.use_handler_docstrings` Adds ability to configure openapi schema generation to use the route handler docstring for operation description. If `False` docstrings are ignored, this is default behavior for backward compatibility. If `True`, `HTTPRouteHandler.description` takes precedence if set, otherwise the docstring is used. * Adds detail to exception raised during signature model creation. * 1.7.2 * add route map extension * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Correct import * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * fix some issues caused when rebasing Co-authored-by: Zachary Dremann <dremann@gmail.com> Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com> Co-authored-by: Na'aman Hirschfeld <nhirschfeld@gmail.com> Co-authored-by: Dane Solberg <danesolberg@gmail.com> Co-authored-by: Peter Schutt <peter@topsport.com.au> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: josepdaniel <36941460+josepdaniel@users.noreply.github.com> Co-authored-by: Joseph Daniel <jdn@logpoint.com> Co-authored-by: cătălin <catalin@roboces.dev> Co-authored-by: Peter Schutt <peter.github@proton.me> Co-authored-by: Tim Wedde <timwedde@icloud.com> Co-authored-by: Harry <harry.lees@gmail.com> Fix issues with Rust route map bindings (#310) * fix poetry.lock error * put auto-initialize behind a feature flag * update poetry.lock * add back missing plain_routes attribute (will be removed) cleanup Misc rust fixes/changes (#312) * Expose RouteMap as a python stub * Remove unused duplicate of rust extension inside starlite dir * Rename module to just `route_map` It's not clear that we need the module to include `_rs` * Remove need for macro for get_attr_and_downcast * Replace macro with a lambda * Use entry.or_insert_with for getting/inserting nodes Should be slightly more efficent: We only have to look up once, rather than twice * Remove unneeded `.into()`/`to_object()` calls * Add back a comment to the top of the route_map type stubs Explain what the file is, and where the implementation is located Update rust setup (#314) * updated folder structure and add pre commit hooks * replace pyi file with py file * update codespell hook * turn off TC006 * update ci Rust Bindings: CI (#317) * updated ci to handle rust testing * update python path * fix coverage * addressed review comments * remove flag preventing install when deps are cached Rust bindings - Some unit tests (#319) * update poetry.lock * add some init tests * add doc comment for gett_attr_and_downcast * derive Default for Node * reformat python scripts for rust tests * First simple routing unit test * Import less of starlite The unit tests for the route_map extension should not need to (transitively) import starlite.route_map * Fix unit tests after rebase * Simplify creation of routes * Avoid stack overflow on drop * Heavily refactor rust code * Convert HandlerGroup to an enum * Include cargo files in sdist * Address comments * Fix pytests added around static handlers * Comment out slotscheck Co-authored-by: Nicholas Ramos <35410160+nramos0@users.noreply.github.com> Issue #177: Add a baseline for Rust path resolution bindings (#270) * add route map extension * change maturin to dev dependency * rust ext: make Node::is_asgi default to false * rust ext: remove unused dependency * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Move rust extension out of starlite folder * Correct import * Include rust source in sdist build * Working extension poetry build * Rename build.py * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * rust ext: remove some uses of `Python::acquire_gil()` * rust ext: don't return `PyResult` for infallible operations * rust ext: hide plain route methods from python interface * rust ext: add route collection parameter to `add_routes` * rust ext: use `IntoPy` trait method for `Node` instead of `as_pydict` * rust ext: refactor parameters for `configure_route_map_node` * rust ext: remove outdated comment * rust_ext: change uses of `cur` to `cur_node` * rust ext: fix typo in route map comments * rust ext: downgrade add_node_to_route_map return value to shared ref * rust_ext: port build_route_middleware_stack into extension util, removing starlite instance dependence * rust ext: add minimal test * Enhancement: Brotli compression middleware (#252) * FEATURE: Added Compression Middleware - Existing Gzip Middleware - Brotli with an optional Gzip fallback. * 1.5.4 * updated pyproject.toml to exclude lines form coverage report * Add tests for `Starlite.construct_route_map` * Address flake8 validation rules * Removes `uuid4()` from within parametrized test cases. Vscode test discovery caches the test case names including parametrized values. This makes having `uuid4()` calls in the parametrized test cases an issue as vscode shows test case failures when it cannot find test cases that it has previously resolved. As the change doesn't affect the utility of the test, it is better to fix the case for vscode users so we don't get the same issue reported in the future. * Addresses cognitive complexity of `DTOFactory.__call__()` by breaking nested logic out into helper methods. Changes no logic, test cov still 100% and existing tests pass. For #203 * updated dependencies * Issue 187 layered parameters (#261) * feat: added parameters to all app layers * feat: refactored handler layer resolution logic * chore: cleanup signature modelling * feat: add layered parameters to kwargs model * fix test coverage * skipped failing test in py 3.7 * update OA params * updated implementation to use ModelField insteam of FieldInfo * add openapi parameter tests * add docs * 1.6.0 * 1.6.1 * Fix route-map path existence test logic (#275) (#277) * added after_response (#279) * added after_response * addressed review comments * Issue 188: resolve exceptions swallowing args (#281) * updated exception init * add tests * 1.6.2 * chore: updated maintainer list (#285) * docs: add cofin as a contributor for maintenance (#286) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Issue #255: allow single element query param in sequence types (#262) * Array handling in query params * Refactor array handling Co-authored-by: Joseph Daniel <jdn@logpoint.com> * docs: add josepdaniel as a contributor for code (#290) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * Updates instructions to install `testing` extra. * LifecycleHook improvements. - Adds `LifecycleHook` for eager evaluation of sync vs async callables and centralisation of handler resolution. Generic on handler response. - Adds aliases `AfterRequestHook`, `AfterResponseHook`, `BeforeRequestHook` that are strongly typed to appropriate handler response type. - Adds support for lifecycle hooks that are instance methods by overwriting handlers assigned to class variables on `Controller` only if they are originally functions. Closes #284 * Enhancement: Tortoise-ORM Plugin (#283) * added tortoise to dev dependencies * added base plugin implementation * add tests * updated plugin implementation * cleanup dependencies * updated implementation * fixed issues * resolved issues * add openapi support * fix tests * updated tests * add docs * fix linter issues * updated tests * 1.7.0 * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity (#292) * Split `openapi.create_paramter_for_handler` into several methods to reduce complexity * Make `openapi.create_paramter_for_handler`'s helper functions public * Revise misleading `openapi.get_recursive_handler_parameters` docstrings * Adds `exceptions.utils.create_exception_response()`. - makes `starlite.exceptions` a sub-package with same api as module it replaces. - adds `starlite.exceptions.utils` module to house the response generation helper function. * Supress warning generated from Tortoise ORM DTO test case. Warning: `RuntimeWarning: coroutine 'TortoiseORMPlugin.to_dict' was never awaited` The warning is expected for the underlying code logic and test case, so safe to supress. * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] * Fixes `!!! important` block and adds `<!-- prettier-ignore -->`. * `orjson` use in `WebSocket.{receive,send}_json()` Implementations are functionally the same as upstream except for orjson usage and we raise our own exceptions. Adds tests for `connection.WebSocket`. Creates `tests/connection` and moved `tests/request` to that location. * Support for SwaggerUI (#302) (#303) * Support for SwaggerUI (#302) * Support for SwaggerUI As per #300 * Use built-in copy method * Add basic sanity check tests for ReDoc and Swagger UI routes (#304) Tests for #303 / #302 These tests check whether the UI handlers: - don't throw an Exception - return 200 OK - return HTML of some form * updated urls, add docs * fix memoization issue Co-authored-by: Tim Wedde <timwedde@icloud.com> * 1.7.1 * Allow Partial to annotate fields of nested classes (#288) * Allow Partial to annotate fields for superclasses * added test to ensure __annotations__ are resolved from parent classes * added test for runtime behaviour of Partial on classes that don't inherit from pydantic.BaseModel * use typing.get_type_hints() instead of __annotations__ for getting class type annotations * raise ImproperlyConfiguredException if class passed to Partial doesn't inherit from BaseModel * added test to ensure Partial raises ImproperlyConfiguredException if an invalid class is given * added Partial section to DTO docs * docs: add Harry-Lees as a contributor for code, doc (#305) * docs: update README.md [skip ci] * docs: update .all-contributorsrc [skip ci] Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> * update docs * Tidy grammar in comment. * `OpenAPIConfig.use_handler_docstrings` Adds ability to configure openapi schema generation to use the route handler docstring for operation description. If `False` docstrings are ignored, this is default behavior for backward compatibility. If `True`, `HTTPRouteHandler.description` takes precedence if set, otherwise the docstring is used. * Adds detail to exception raised during signature model creation. * 1.7.2 * add route map extension * Build rust project with poetry * Move cargo stuff entirely within the extensions/rust dir * Correct import * Ignore build directory * fix .gitignore order * rust ext: refactor and rename route map module; added resolve_asgi_app() * reinstall lock file * fix some issues caused when rebasing Co-authored-by: Zachary Dremann <dremann@gmail.com> Co-authored-by: Cody Fincher <204685+cofin@users.noreply.github.com> Co-authored-by: Na'aman Hirschfeld <nhirschfeld@gmail.com> Co-authored-by: Dane Solberg <danesolberg@gmail.com> Co-authored-by: Peter Schutt <peter@topsport.com.au> Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: josepdaniel <36941460+josepdaniel@users.noreply.github.com> Co-authored-by: Joseph Daniel <jdn@logpoint.com> Co-authored-by: cătălin <catalin@roboces.dev> Co-authored-by: Peter Schutt <peter.github@proton.me> Co-authored-by: Tim Wedde <timwedde@icloud.com> Co-authored-by: Harry <harry.lees@gmail.com> Fix issues with Rust route map bindings (#310) * fix poetry.lock error * put auto-initialize behind a feature flag * update poetry.lock * add back missing plain_routes attribute (will be removed) cleanup Misc rust fixes/changes (#312) * Expose RouteMap as a python stub * Remove unused duplicate of rust extension inside starlite dir * Rename module to just `route_map` It's not clear that we need the module to include `_rs` * Remove need for macro for get_attr_and_downcast * Replace macro with a lambda * Use entry.or_insert_with for getting/inserting nodes Should be slightly more efficent: We only have to look up once, rather than twice * Remove unneeded `.into()`/`to_object()` calls * Add back a comment to the top of the route_map type stubs Explain what the file is, and where the implementation is located Update rust setup (#314) * updated folder structure and add pre commit hooks * replace pyi file with py file * update codespell hook * turn off TC006 * update ci Rust Bindings: CI (#317) * updated ci to handle rust testing * update python path * fix coverage * addressed review comments * remove flag preventing install when deps are cached Rust bindings - Some unit tests (#319) * update poetry.lock * add some init tests * add doc comment for gett_attr_and_downcast * derive Default for Node * reformat python scripts for rust tests
It appears that there is not sufficent benefit from this. |
Starlite currently resolves paths using a tree structure, but in python. This is quite slow. It would be very helpful if we could create custom bindings in a low level and substantially faster language to implement the tree and its required parsing methods.
The data structure that is often used for this purpose is called a "radix prefix tree". This is not necessarily the only option we have - but its a strong one.
PRs are welcome, as are discussions.
The text was updated successfully, but these errors were encountered: