Skip to content

Commit 87b67ad

Browse files
committed
fixed nasty bug with Fast_API add_routes* methods, which where not using the "Type_Safe and Type_Safe__Primitive" aware methods
fixed bug in create_wrapper which was not capturing the return_type added test_Fast_API__routes refactored out the Fast_API__CLI into the _to_refactor_to_separate_project folder same with Fast_API__Routes__Paths (since this will need to be redone with the using the new routes parser)
1 parent f36b0a2 commit 87b67ad

File tree

15 files changed

+241
-95
lines changed

15 files changed

+241
-95
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# from Routes__Config
2+
3+
def routes__json(self):
4+
return Fast_API__Routes__Paths(app=self.app).routes_tree()
5+
6+
def routes__html(self):
7+
html_content = Fast_API__Routes__Paths(app=self.app).routes_html()
8+
return HTMLResponse(content=html_content)
9+
10+
11+
def setup_routes(self):
12+
self.add_route_get(self.routes__json )
13+
self.add_route_get(self.routes__html )

osbot_fast_api/api/Fast_API.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from osbot_fast_api.api.middlewares.Middleware__Request_ID import Middleware__Request_ID
2+
from osbot_fast_api.api.routes.Fast_API__Route__Helper import Fast_API__Route__Helper
23
from osbot_fast_api.api.schemas.Schema__Fast_API__Config import Schema__Fast_API__Config
34
from osbot_utils.type_safe.Type_Safe import Type_Safe
45
from osbot_utils.decorators.lists.index_by import index_by
@@ -20,7 +21,11 @@ class Fast_API(Type_Safe):
2021
def __init__(self, **kwargs):
2122
super().__init__(**kwargs)
2223
if not self.config.name:
23-
self.config.name = self.__class__.__name__ # this makes the api name more user friendly
24+
self.config.name = self.__class__.__name__ # this makes the api name more user-friendly
25+
26+
@cache_on_self
27+
def route_helper(self):
28+
return Fast_API__Route__Helper()
2429

2530
# todo: improve the error handling of validation errors (namely from Type_Safe_Primitive)
2631
# see code example in https://claude.ai/chat/f443e322-fa43-487f-9dd9-2d4cfb261b1e
@@ -55,16 +60,25 @@ def add_flask_app(self, path, flask_app):
5560
self.app().mount(path, WSGIMiddleware(flask_app))
5661
return self
5762

58-
def add_route(self,function, methods):
59-
path = '/' + function.__name__.replace('_', '-')
60-
self.app().add_api_route(path=path, endpoint=function, methods=methods)
63+
def add_route(self, function, methods): # Register a route with Type_Safe support
64+
self.route_helper().add_route(self.app(), function, methods)
6165
return self
6266

63-
def add_route_get(self, function):
64-
return self.add_route(function=function, methods=['GET'])
67+
def add_route_get(self, function): # Register GET route with Type_Safe support
68+
self.route_helper().add_route_get(self.app(), function)
69+
return self
6570

66-
def add_route_post(self, function):
67-
return self.add_route(function=function, methods=['POST'])
71+
def add_route_post(self, function): # Register POST route with Type_Safe support
72+
self.route_helper().add_route_post(self.app(), function)
73+
return self
74+
75+
def add_route_put(self, function): # Register PUT route with Type_Safe support
76+
self.route_helper().add_route_put(self.app(), function)
77+
return self
78+
79+
def add_route_delete(self, function): # Register DELETE route with Type_Safe support
80+
self.route_helper().add_route_delete(self.app(), function)
81+
return self
6882

6983
def add_routes(self, class_routes):
7084
class_routes(app=self.app()).setup()
@@ -153,7 +167,6 @@ def routes_paths(self, include_default=False, expand_mounts=False):
153167
def routes_paths_all(self):
154168
return self.routes_paths(include_default=True, expand_mounts=True)
155169

156-
157170
def setup_middlewares(self): # overwrite to add more middlewares (NOTE: the middleware execution is the reverse of the order they are added)
158171
self.setup_middleware__detect_disconnect()
159172
self.setup_middleware__cors ()

osbot_fast_api/api/routes/Routes__Config.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
from fastapi import Response
2-
from fastapi.responses import HTMLResponse
32
from osbot_fast_api.api.decorators.route_path import route_path
43
from osbot_fast_api.api.routes.Fast_API__Routes import Fast_API__Routes
54
from osbot_fast_api.api.transformers.OpenAPI__To__Python import OpenAPI__To__Python
6-
from osbot_fast_api.utils.Fast_API__Routes__Paths import Fast_API__Routes__Paths
75
from osbot_fast_api.utils.Fast_API__Server_Info import fast_api__server_info
86
from osbot_fast_api.utils.Version import version__osbot_fast_api
97

@@ -21,13 +19,6 @@ def status(self):
2119
def version(self):
2220
return {'version': version__osbot_fast_api}
2321

24-
def routes__json(self):
25-
return Fast_API__Routes__Paths(app=self.app).routes_tree()
26-
27-
def routes__html(self):
28-
html_content = Fast_API__Routes__Paths(app=self.app).routes_html()
29-
return HTMLResponse(content=html_content)
30-
3122
@route_path('/openapi.py')
3223
def openapi_python(self):
3324
open_api_to_python = OpenAPI__To__Python()
@@ -40,6 +31,4 @@ def setup_routes(self):
4031
self.add_route_get(self.info )
4132
self.add_route_get(self.status )
4233
self.add_route_get(self.version )
43-
self.add_route_get(self.routes__json )
44-
self.add_route_get(self.routes__html )
4534
self.add_route_get(self.openapi_python)

osbot_fast_api/api/routes/Type_Safe__Route__Wrapper.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,18 @@ def create_wrapper(self, function : Callable , # Origin
2020
if not signature.primitive_conversions and not signature.type_safe_conversions and not signature.return_needs_conversion:
2121
return function # No conversion needed - return original
2222

23-
if signature.has_body_params: # Different wrappers for different scenarios
24-
return self.create_body_wrapper(function, signature)
23+
if signature.has_body_params: # Different wrappers for different scenarios
24+
wrapper_function = self.create_body_wrapper(function, signature)
2525
else:
26-
return self.create_query_wrapper(function, signature)
26+
wrapper_function = self.create_query_wrapper(function, signature)
27+
28+
if signature.return_type is not None:
29+
wrapper_function.__original_return_type__ = signature.return_type # Preserve original return type metadata for route extractors
30+
31+
if hasattr(function, '__route_path__'): # Also preserve route_path decorator if it exists
32+
wrapper_function.__route_path__ = function.__route_path__
33+
34+
return wrapper_function
2735

2836
@type_safe
2937
def create_body_wrapper(self, function : Callable , # Function to wrap

osbot_fast_api/api/schemas/consts/consts__Fast_API.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@
2727
EXPECTED_ROUTES_METHODS = [ 'info' ,
2828
'openapi_python' ,
2929
'redirect_to_docs',
30-
'routes__html' ,
31-
'routes__json' ,
30+
#'routes__html' ,
31+
#'routes__json' ,
3232
'set_auth_cookie' ,
3333
'set_cookie_form' ,
3434
'status' ,
3535
'version' ]
3636
EXPECTED_ROUTES__CONFIG = ['/config/info' ,
3737
'/config/openapi.py' ,
38-
'/config/routes/html' ,
39-
'/config/routes/json' ,
38+
#'/config/routes/html' ,
39+
#'/config/routes/json' ,
4040
'/config/status' ,
4141
'/config/version' ]
4242
EXPECTED_ROUTES__SET_COOKIE = ['/auth/set-auth-cookie' ,
@@ -52,8 +52,8 @@
5252
ROUTES__CONFIG = [{ 'http_methods': ['GET' ], 'http_path': Safe_Str__Fast_API__Route__Prefix('/config/info' ) , 'method_name': 'info' },
5353
{ 'http_methods': ['GET' ], 'http_path': Safe_Str__Fast_API__Route__Prefix('/config/status' ) , 'method_name': 'status' },
5454
{ 'http_methods': ['GET' ], 'http_path': Safe_Str__Fast_API__Route__Prefix('/config/version' ) , 'method_name': 'version' },
55-
{ 'http_methods': ['GET' ], 'http_path': Safe_Str__Fast_API__Route__Prefix('/config/routes/json' ) , 'method_name': 'routes__json' },
56-
{ 'http_methods': ['GET' ], 'http_path': Safe_Str__Fast_API__Route__Prefix('/config/routes/html' ) , 'method_name': 'routes__html' },
55+
#{ 'http_methods': ['GET' ], 'http_path': Safe_Str__Fast_API__Route__Prefix('/config/routes/json' ) , 'method_name': 'routes__json' },
56+
#{ 'http_methods': ['GET' ], 'http_path': Safe_Str__Fast_API__Route__Prefix('/config/routes/html' ) , 'method_name': 'routes__html' },
5757
{ 'http_methods': ['GET' ], 'http_path': Safe_Str__Fast_API__Route__Prefix('/config/openapi.py' ) , 'method_name': 'openapi_python' },
5858
{ 'http_methods': ['GET' ], 'http_path': Safe_Str__Fast_API__Route__Prefix('/auth/set-cookie-form') , 'method_name': 'set_cookie_form' },
5959
{ 'http_methods': ['POST' ], 'http_path': Safe_Str__Fast_API__Route__Prefix('/auth/set-auth-cookie') , 'method_name': 'set_auth_cookie' },]

osbot_fast_api/client/Fast_API__Route__Extractor.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import inspect
12
from typing import List, Union
23
from pydantic_core import PydanticUndefined
34
from osbot_fast_api.api.schemas.routes.Schema__Fast_API__Route import Schema__Fast_API__Route
@@ -16,8 +17,8 @@
1617
from starlette.middleware.wsgi import WSGIMiddleware
1718
from starlette.routing import Mount, Route
1819
from starlette.staticfiles import StaticFiles
19-
from osbot_fast_api.api.schemas.safe_str.Safe_Str__Fast_API__Route__Prefix import Safe_Str__Fast_API__Route__Prefix
20-
from osbot_fast_api.api.schemas.enums.Enum__Fast_API__Route__Type import Enum__Fast_API__Route__Type
20+
from osbot_fast_api.api.schemas.safe_str.Safe_Str__Fast_API__Route__Prefix import Safe_Str__Fast_API__Route__Prefix
21+
from osbot_fast_api.api.schemas.enums.Enum__Fast_API__Route__Type import Enum__Fast_API__Route__Type
2122

2223
class Fast_API__Route__Extractor(Type_Safe): # Dedicated class for route extraction
2324
app : FastAPI
@@ -185,10 +186,10 @@ def extract__body_params(self, route: APIRoute):
185186
return body_params
186187

187188
@type_safe
188-
def extract__return_type(self, route: APIRoute):
189-
# Get return type from endpoint callable
189+
def extract__return_type(self, route: APIRoute): # Get return type from endpoint callable
190190
if hasattr(route, 'endpoint') and route.endpoint:
191-
import inspect
191+
if hasattr(route.endpoint, '__original_return_type__'): # check if Type_Safe__Route__Wrapper added the __original_return_type__
192+
return route.endpoint.__original_return_type__
192193
sig = inspect.signature(route.endpoint)
193194
if sig.return_annotation != inspect.Parameter.empty:
194195
return sig.return_annotation

0 commit comments

Comments
 (0)