Skip to content

Commit 5f46aca

Browse files
committed
Merge dev into main
2 parents 5ff33b9 + da7b0f4 commit 5f46aca

16 files changed

Lines changed: 1841 additions & 234 deletions

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# OSBot-Fast-API
22

3-
![Current Release](https://img.shields.io/badge/release-v0.31.0-blue)
3+
![Current Release](https://img.shields.io/badge/release-v0.31.2-blue)
44
![Python](https://img.shields.io/badge/python-3.8+-green)
55
![FastAPI](https://img.shields.io/badge/FastAPI-0.100+-red)
66
![Type-Safe](https://img.shields.io/badge/Type--Safe-✓-brightgreen)

docs/llm-brief/v3.28.0__osbot-utils-safe-primitives__reference-guide.md

Lines changed: 1455 additions & 0 deletions
Large diffs are not rendered by default.

osbot_fast_api/api/Fast_API.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ def client(self):
106106
from starlette.testclient import TestClient # moved here for performance reasons
107107
return TestClient(self.app())
108108

109+
def config__no_default_routes(self): self.config.default_routes = False ; return self
110+
def config__no_api_key (self): self.config.enable_api_key = False ; return self
111+
def config__no_docs_offline (self): self.config.docs_offline = False ; return self
112+
113+
109114
def enable_api_key(self):
110115
self.config.enable_api_key = True
111116
return self

osbot_fast_api/api/routes/Routes__Config.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77

88
# todo: these are actually routes, so we should move them into a better location
99
# maybe 'default_routes' or something similar
10+
11+
ROUTES_PATHS__CONFIG = ['/config/info' ,
12+
'/config/openapi.py' ,
13+
'/config/status' ,
14+
'/config/version' ]
15+
1016
class Routes__Config(Fast_API__Routes):
1117
tag = 'config'
1218

osbot_fast_api/api/routes/Routes__Set_Cookie.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ class Schema__Set_Cookie(Type_Safe):
1212
# todo: these are actually routes, so we should move them into a better location
1313
# maybe 'default_routes' or something similar
1414

15+
ROUTES_PATHS__SET_COOKIE = ['/auth/set-auth-cookie' ,
16+
'/auth/set-cookie-form']
17+
18+
1519
class Routes__Set_Cookie(Fast_API__Routes):
1620
tag: str = 'auth'
1721

osbot_fast_api/api/transformers/Type_Safe__To__BaseModel.py

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,22 @@ def convert_class(self, type_safe_class: Type[Type_Safe]
2020

2121
annotations = type_safe_cache.get_class_annotations(type_safe_class) # Get class annotations (using type_safe_cache)
2222
pydantic_fields = {} # Build Pydantic fields
23+
cls_kwargs = type_safe_class.__cls_kwargs__() # Get class kwargs with defaults once
2324

2425
for field_name, field_type in annotations:
2526
pydantic_type = self.convert_type(field_type) # Convert Type_Safe types to Pydantic
26-
default_value = self.get_default_value(type_safe_class, field_name) # Get default value if exists
27-
28-
if default_value is not None: # Create field with proper config
29-
pydantic_fields[field_name] = (pydantic_type, default_value)
30-
else:
27+
has_default = field_name in cls_kwargs # Check if field has any default (including None)
28+
29+
if has_default:
30+
default_value = cls_kwargs[field_name]
31+
default_value = self.normalize_default_value(default_value) # Normalize collections
32+
33+
if default_value is None: # Explicit None default - make Optional
34+
pydantic_type = Optional[pydantic_type]
35+
pydantic_fields[field_name] = (pydantic_type, None)
36+
else:
37+
pydantic_fields[field_name] = (pydantic_type, default_value)
38+
else: # No default - required field
3139
pydantic_fields[field_name] = (pydantic_type, Field(...))
3240

3341
model_name = f"{type_safe_class.__name__}__BaseModel" # Generate model name
@@ -93,23 +101,17 @@ def convert_type(self, type_safe_type: Any # Type a
93101

94102
return type_safe_type # Return as-is for standard types
95103

96-
def get_default_value(self, type_safe_class: Type[Type_Safe], # Class to get default from
97-
field_name: str # Field name to check
98-
) -> Any: # Returns default value or None
99-
cls_kwargs = type_safe_class.__cls_kwargs__() # Get class kwargs with defaults
104+
def get_default_value(self, type_safe_class: Type[Type_Safe], # Class to get default from
105+
field_name: str # Field name to check
106+
) -> Any: # Returns default value or None
107+
cls_kwargs = type_safe_class.__cls_kwargs__() # Get class kwargs with defaults
100108

101109
if field_name in cls_kwargs:
102-
value = cls_kwargs[field_name]
103-
if isinstance(value, Type_Safe__List): # Convert Type_Safe collections
104-
return list(value)
105-
elif isinstance(value, Type_Safe__Dict):
106-
return dict(value)
107-
elif isinstance(value, Type_Safe__Set):
108-
return list(value) # Convert set to list for Pydantic
109-
return value
110+
return self.normalize_default_value(cls_kwargs[field_name])
110111

111112
return None
112113

114+
113115
def extract_instance_data(self, type_safe_instance: Type_Safe # Instance to extract data from
114116
) -> Dict[str, Any]: # Returns dict of instance data
115117
data = {}
@@ -163,5 +165,15 @@ def convert_dict(self, type_safe_dict: Type_Safe__Dict
163165

164166
return result
165167

168+
def normalize_default_value(self, value: Any # Default value to normalize
169+
) -> Any: # Returns normalized value
170+
if isinstance(value, Type_Safe__List): # Convert Type_Safe collections
171+
return list(value)
172+
elif isinstance(value, Type_Safe__Dict):
173+
return dict(value)
174+
elif isinstance(value, Type_Safe__Set):
175+
return list(value) # Convert set to list for Pydantic
176+
return value
177+
166178

167179
type_safe__to__basemodel = Type_Safe__To__BaseModel() # Singleton instance for convenience (and to have a more global model_cache)

osbot_fast_api/api/transformers/Type_Safe__To__Json.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
from typing import Type, Dict, Any, get_args, Union, Optional, Tuple
2-
from osbot_utils.type_safe.Type_Safe import Type_Safe
3-
from osbot_utils.type_safe.Type_Safe__Primitive import Type_Safe__Primitive
4-
from osbot_utils.type_safe.primitives.core.Safe_Str import Safe_Str
5-
from osbot_utils.type_safe.primitives.core.Safe_Int import Safe_Int
6-
from osbot_utils.type_safe.primitives.core.Safe_Float import Safe_Float
7-
from osbot_utils.type_safe.type_safe_core.decorators.type_safe import type_safe
8-
from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Cache import type_safe_cache
1+
from typing import Type, Dict, Any, get_args, Union, Optional, Tuple
2+
from osbot_utils.type_safe.Type_Safe import Type_Safe
3+
from osbot_utils.type_safe.Type_Safe__Primitive import Type_Safe__Primitive
4+
from osbot_utils.type_safe.primitives.core.Safe_Str import Safe_Str
5+
from osbot_utils.type_safe.primitives.core.Safe_Int import Safe_Int
6+
from osbot_utils.type_safe.primitives.core.Safe_Float import Safe_Float
7+
from osbot_utils.type_safe.type_safe_core.decorators.type_safe import type_safe
8+
from osbot_utils.type_safe.type_safe_core.shared.Type_Safe__Cache import type_safe_cache
99

1010

1111
class Type_Safe__To__Json(Type_Safe): # Converts Type_Safe classes to JSON Schema (draft-07 compatible)
@@ -14,6 +14,9 @@ class Type_Safe__To__Json(Type_Safe): # Converts Type_Safe classes to JSON
1414
include_examples : bool = False
1515
strict_mode : bool = False # If True, includes all Type_Safe constraints
1616

17+
# todo: the @type_safe here breaks some of the cache behaviour below since the @type_safe will
18+
# convert the Dict to Type_Safe__Dict which means the returned objects are not the same (but from the cached value, so the performance implications might not be that big)
19+
# (see if this has any side effects or main performance implications)
1720
@type_safe
1821
def convert_class(self, type_safe_class : Type[Type_Safe] , # Type_Safe class to convert
1922
title : str = None , # Optional schema title

osbot_fast_api/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.31.0
1+
v0.31.2

0 commit comments

Comments
 (0)