Skip to content

Commit b103452

Browse files
committed
major improvements to Schema__Endpoint__Param and it's extraction logic
1 parent 2ebe86a commit b103452

8 files changed

Lines changed: 155 additions & 59 deletions

osbot_fast_api/client/Fast_API__Contract__Extractor.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ def extract_contract(self) -> Schema__Service__Contract:
3939
all_routes = self.fast_api__all_routes()
4040
routes_by_module = self.organize_routes__by_tag(all_routes)
4141

42-
for module_name, route_info in routes_by_module.items():
43-
module = Schema__Routes__Module(module_name = module_name ,
44-
route_classes = route_info['classes'],
45-
endpoints = [] )
42+
for module_name, route_info in routes_by_module.by_tag.items():
43+
module = Schema__Routes__Module(module_name = module_name ,
44+
route_classes = route_info.classes,
45+
endpoints = [] )
4646

47-
for route_data in route_info['routes']: # Now returns a list of contracts
48-
endpoint_contracts = self._extract_endpoint_contract(route_data)
47+
for route_data in route_info.routes: # Now returns a list of contracts
48+
endpoint_contracts = self.extract_endpoint_contract(route_data)
4949
for endpoint in endpoint_contracts:
5050
if endpoint:
5151
endpoint.route_module = module_name
@@ -79,8 +79,8 @@ def organize_routes__by_tag(self, routes: List[Schema__Fast_API__Route] # List
7979
return routes_by_tag
8080

8181

82-
def _extract_endpoint_contract(self, route_data: Schema__Fast_API__Route
83-
) -> List[Schema__Endpoint__Contract]: # Now returns a List
82+
def extract_endpoint_contract(self, route_data: Schema__Fast_API__Route
83+
) -> List[Schema__Endpoint__Contract]: # Now returns a List
8484
method_name = route_data.method_name
8585
http_path = route_data.http_path
8686
http_methods = route_data.http_methods
@@ -112,11 +112,9 @@ def _extract_endpoint_contract(self, route_data: Schema__Fast_API__Route
112112
param_pattern = r'\{(\w+)\}'
113113
path_params = re.findall(param_pattern, http_path)
114114
for param_name in path_params:
115-
endpoint.path_params.append(Schema__Endpoint__Param(
116-
name = param_name,
117-
location = Enum__Param__Location.PATH,
118-
param_type = 'str'
119-
))
115+
endpoint.path_params.append(Schema__Endpoint__Param(name = param_name,
116+
location = Enum__Param__Location.PATH,
117+
param_type = 'str' ))
120118
break
121119

122120
# Enhance with function signature analysis (same for all methods)

osbot_fast_api/client/Fast_API__Route__Extractor.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
from typing import List, Union
2+
3+
from pydantic_core import PydanticUndefinedType, PydanticUndefined
4+
5+
from osbot_utils.utils.Dev import pprint
6+
7+
from osbot_fast_api.client.schemas.Schema__Endpoint__Param import Schema__Endpoint__Param
8+
from osbot_fast_api.client.schemas.enums.Enum__Param__Location import Enum__Param__Location
29
from osbot_utils.type_safe.type_safe_core.collections.Type_Safe__List import Type_Safe__List
310
from osbot_fast_api.schemas.consts__Fast_API import FAST_API_DEFAULT_ROUTES_PATHS
411
from osbot_utils.type_safe.Type_Safe import Type_Safe
@@ -61,16 +68,18 @@ def create_api_route(self, route : Union[APIRoute, Route] , # Fa
6168
http_methods = [] # Convert methods to enum
6269
for method in sorted(route.methods):
6370
http_methods.append(Enum__Http__Method(method))
64-
method_name = Safe_Str__Id(route.name)
65-
route_class = self.extract_route_class(route) # Determine route class if from Routes__* pattern
71+
method_name = Safe_Str__Id(route.name)
72+
route_class = self.extract__route_class(route) # Determine route class if from Routes__* pattern
73+
path_params = self.extract__path_params(route=route)
6674
if type(route_class) is APIRoute: # only the APIRoute class has the
6775
route_tags = route.tags # .tags method
6876
else:
69-
route_tags = None
77+
route_tags = None
7078
return Schema__Fast_API__Route(http_path = path ,
7179
method_name = method_name ,
7280
http_methods = http_methods ,
7381
route_type = Enum__Route__Type.API_ROUTE ,
82+
path_params = path_params ,
7483
route_tags = route_tags ,
7584
route_class = route_class ,
7685
is_default = self.is_default_route(str(path)))
@@ -112,6 +121,16 @@ def extract_mount_routes(self, mount: Mount , # Mo
112121

113122
return routes
114123

124+
@type_safe
125+
def extract__path_params(self, route: APIRoute):
126+
path_params = []
127+
for param in route.dependant.path_params:
128+
path_params.append(Schema__Endpoint__Param(name = param.name ,
129+
location = Enum__Param__Location.PATH ,
130+
param_type = param.type_ ,
131+
required = param.required ))
132+
return path_params
133+
115134
@type_safe
116135
def create_websocket_route(self, route : APIWebSocketRoute , # WebSocket route
117136
path : Safe_Str__Fast_API__Route__Prefix
@@ -138,7 +157,7 @@ def _combine_paths(self, prefix : Safe_Str__Fast_API__Route__Prefix, # Prefix
138157
def is_default_route(self, path: str) -> bool: # Check if default route
139158
return path in FAST_API_DEFAULT_ROUTES_PATHS
140159

141-
def extract_route_class(self, route) -> Safe_Str__Id: # Extract class name (in most cases it will be something like Routes__* )
160+
def extract__route_class(self, route) -> Safe_Str__Id: # Extract class name (in most cases it will be something like Routes__* )
142161
route_class = None
143162
if hasattr(route, 'endpoint'):
144163
if hasattr(route.endpoint, '__self__'): # first try to get the class name (if inside a class)
Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
1-
from typing import Any
1+
from typing import Any, Type
22
from osbot_utils.type_safe.Type_Safe import Type_Safe
33
from osbot_utils.type_safe.primitives.domains.identifiers.safe_str.Safe_Str__Id import Safe_Str__Id
4-
from osbot_utils.type_safe.primitives.domains.common.safe_str.Safe_Str__Text import Safe_Str__Text
54
from osbot_fast_api.client.schemas.enums.Enum__Param__Location import Enum__Param__Location
6-
from osbot_fast_api.client.schemas.safe_str.Safe_Str__Python_Type import Safe_Str__Python__Type
7-
85

96
class Schema__Endpoint__Param(Type_Safe):
107
name : Safe_Str__Id # Parameter name
118
location : Enum__Param__Location # Where parameter appears
12-
param_type : Safe_Str__Python__Type # Type as string (for serialization)
9+
param_type : Type
1310
required : bool = True # Is parameter required?
14-
default : Any = None # Default value if any
15-
description : Safe_Str__Text = None # Parameter documentation

osbot_fast_api/schemas/routes/Schema__Fast_API__Route.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from typing import List
2+
3+
from osbot_fast_api.client.schemas.Schema__Endpoint__Param import Schema__Endpoint__Param
24
from osbot_utils.type_safe.Type_Safe import Type_Safe
35
from osbot_utils.type_safe.primitives.domains.identifiers.safe_str.Safe_Str__Id import Safe_Str__Id
46
from osbot_fast_api.schemas.Safe_Str__Fast_API__Route__Prefix import Safe_Str__Fast_API__Route__Prefix
@@ -16,4 +18,5 @@ class Schema__Fast_API__Route(Type_Safe):
1618
route_type : Enum__Route__Type = Enum__Route__Type.API_ROUTE
1719
route_class : Safe_Str__Id = None # Class name if from Routes__* class
1820
route_tags : List[Safe_Str__Fast_API__Route__Tag] = None # Route tag/category
21+
path_params : List[Schema__Endpoint__Param ] = None
1922

tests/unit/client/test_Fast_API__Contract__Extractor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def test__extract_endpoint_contract(self):
105105
'http_path' : '/users/{user_id}' ,
106106
'http_methods': ['GET'] }
107107

108-
endpoint = _._extract_endpoint_contract(route_data)
108+
endpoint = _.extract_endpoint_contract(route_data)
109109

110110
assert type(endpoint) is Schema__Endpoint__Contract
111111
assert endpoint.operation_id == 'get_user__user_id'

0 commit comments

Comments
 (0)