about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/fastapi/utils.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/fastapi/utils.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-4a52a71956a8d46fcb7294ac71734504bb09bcc2.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/fastapi/utils.py')
-rw-r--r--.venv/lib/python3.12/site-packages/fastapi/utils.py220
1 files changed, 220 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/fastapi/utils.py b/.venv/lib/python3.12/site-packages/fastapi/utils.py
new file mode 100644
index 00000000..4c7350fe
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/fastapi/utils.py
@@ -0,0 +1,220 @@
+import re
+import warnings
+from dataclasses import is_dataclass
+from typing import (
+    TYPE_CHECKING,
+    Any,
+    Dict,
+    MutableMapping,
+    Optional,
+    Set,
+    Type,
+    Union,
+    cast,
+)
+from weakref import WeakKeyDictionary
+
+import fastapi
+from fastapi._compat import (
+    PYDANTIC_V2,
+    BaseConfig,
+    ModelField,
+    PydanticSchemaGenerationError,
+    Undefined,
+    UndefinedType,
+    Validator,
+    lenient_issubclass,
+)
+from fastapi.datastructures import DefaultPlaceholder, DefaultType
+from pydantic import BaseModel, create_model
+from pydantic.fields import FieldInfo
+from typing_extensions import Literal
+
+if TYPE_CHECKING:  # pragma: nocover
+    from .routing import APIRoute
+
+# Cache for `create_cloned_field`
+_CLONED_TYPES_CACHE: MutableMapping[Type[BaseModel], Type[BaseModel]] = (
+    WeakKeyDictionary()
+)
+
+
+def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool:
+    if status_code is None:
+        return True
+    # Ref: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#patterned-fields-1
+    if status_code in {
+        "default",
+        "1XX",
+        "2XX",
+        "3XX",
+        "4XX",
+        "5XX",
+    }:
+        return True
+    current_status_code = int(status_code)
+    return not (current_status_code < 200 or current_status_code in {204, 205, 304})
+
+
+def get_path_param_names(path: str) -> Set[str]:
+    return set(re.findall("{(.*?)}", path))
+
+
+def create_model_field(
+    name: str,
+    type_: Any,
+    class_validators: Optional[Dict[str, Validator]] = None,
+    default: Optional[Any] = Undefined,
+    required: Union[bool, UndefinedType] = Undefined,
+    model_config: Type[BaseConfig] = BaseConfig,
+    field_info: Optional[FieldInfo] = None,
+    alias: Optional[str] = None,
+    mode: Literal["validation", "serialization"] = "validation",
+) -> ModelField:
+    class_validators = class_validators or {}
+    if PYDANTIC_V2:
+        field_info = field_info or FieldInfo(
+            annotation=type_, default=default, alias=alias
+        )
+    else:
+        field_info = field_info or FieldInfo()
+    kwargs = {"name": name, "field_info": field_info}
+    if PYDANTIC_V2:
+        kwargs.update({"mode": mode})
+    else:
+        kwargs.update(
+            {
+                "type_": type_,
+                "class_validators": class_validators,
+                "default": default,
+                "required": required,
+                "model_config": model_config,
+                "alias": alias,
+            }
+        )
+    try:
+        return ModelField(**kwargs)  # type: ignore[arg-type]
+    except (RuntimeError, PydanticSchemaGenerationError):
+        raise fastapi.exceptions.FastAPIError(
+            "Invalid args for response field! Hint: "
+            f"check that {type_} is a valid Pydantic field type. "
+            "If you are using a return type annotation that is not a valid Pydantic "
+            "field (e.g. Union[Response, dict, None]) you can disable generating the "
+            "response model from the type annotation with the path operation decorator "
+            "parameter response_model=None. Read more: "
+            "https://fastapi.tiangolo.com/tutorial/response-model/"
+        ) from None
+
+
+def create_cloned_field(
+    field: ModelField,
+    *,
+    cloned_types: Optional[MutableMapping[Type[BaseModel], Type[BaseModel]]] = None,
+) -> ModelField:
+    if PYDANTIC_V2:
+        return field
+    # cloned_types caches already cloned types to support recursive models and improve
+    # performance by avoiding unnecessary cloning
+    if cloned_types is None:
+        cloned_types = _CLONED_TYPES_CACHE
+
+    original_type = field.type_
+    if is_dataclass(original_type) and hasattr(original_type, "__pydantic_model__"):
+        original_type = original_type.__pydantic_model__
+    use_type = original_type
+    if lenient_issubclass(original_type, BaseModel):
+        original_type = cast(Type[BaseModel], original_type)
+        use_type = cloned_types.get(original_type)
+        if use_type is None:
+            use_type = create_model(original_type.__name__, __base__=original_type)
+            cloned_types[original_type] = use_type
+            for f in original_type.__fields__.values():
+                use_type.__fields__[f.name] = create_cloned_field(
+                    f, cloned_types=cloned_types
+                )
+    new_field = create_model_field(name=field.name, type_=use_type)
+    new_field.has_alias = field.has_alias  # type: ignore[attr-defined]
+    new_field.alias = field.alias  # type: ignore[misc]
+    new_field.class_validators = field.class_validators  # type: ignore[attr-defined]
+    new_field.default = field.default  # type: ignore[misc]
+    new_field.required = field.required  # type: ignore[misc]
+    new_field.model_config = field.model_config  # type: ignore[attr-defined]
+    new_field.field_info = field.field_info
+    new_field.allow_none = field.allow_none  # type: ignore[attr-defined]
+    new_field.validate_always = field.validate_always  # type: ignore[attr-defined]
+    if field.sub_fields:  # type: ignore[attr-defined]
+        new_field.sub_fields = [  # type: ignore[attr-defined]
+            create_cloned_field(sub_field, cloned_types=cloned_types)
+            for sub_field in field.sub_fields  # type: ignore[attr-defined]
+        ]
+    if field.key_field:  # type: ignore[attr-defined]
+        new_field.key_field = create_cloned_field(  # type: ignore[attr-defined]
+            field.key_field,  # type: ignore[attr-defined]
+            cloned_types=cloned_types,
+        )
+    new_field.validators = field.validators  # type: ignore[attr-defined]
+    new_field.pre_validators = field.pre_validators  # type: ignore[attr-defined]
+    new_field.post_validators = field.post_validators  # type: ignore[attr-defined]
+    new_field.parse_json = field.parse_json  # type: ignore[attr-defined]
+    new_field.shape = field.shape  # type: ignore[attr-defined]
+    new_field.populate_validators()  # type: ignore[attr-defined]
+    return new_field
+
+
+def generate_operation_id_for_path(
+    *, name: str, path: str, method: str
+) -> str:  # pragma: nocover
+    warnings.warn(
+        "fastapi.utils.generate_operation_id_for_path() was deprecated, "
+        "it is not used internally, and will be removed soon",
+        DeprecationWarning,
+        stacklevel=2,
+    )
+    operation_id = f"{name}{path}"
+    operation_id = re.sub(r"\W", "_", operation_id)
+    operation_id = f"{operation_id}_{method.lower()}"
+    return operation_id
+
+
+def generate_unique_id(route: "APIRoute") -> str:
+    operation_id = f"{route.name}{route.path_format}"
+    operation_id = re.sub(r"\W", "_", operation_id)
+    assert route.methods
+    operation_id = f"{operation_id}_{list(route.methods)[0].lower()}"
+    return operation_id
+
+
+def deep_dict_update(main_dict: Dict[Any, Any], update_dict: Dict[Any, Any]) -> None:
+    for key, value in update_dict.items():
+        if (
+            key in main_dict
+            and isinstance(main_dict[key], dict)
+            and isinstance(value, dict)
+        ):
+            deep_dict_update(main_dict[key], value)
+        elif (
+            key in main_dict
+            and isinstance(main_dict[key], list)
+            and isinstance(update_dict[key], list)
+        ):
+            main_dict[key] = main_dict[key] + update_dict[key]
+        else:
+            main_dict[key] = value
+
+
+def get_value_or_default(
+    first_item: Union[DefaultPlaceholder, DefaultType],
+    *extra_items: Union[DefaultPlaceholder, DefaultType],
+) -> Union[DefaultPlaceholder, DefaultType]:
+    """
+    Pass items or `DefaultPlaceholder`s by descending priority.
+
+    The first one to _not_ be a `DefaultPlaceholder` will be returned.
+
+    Otherwise, the first item (a `DefaultPlaceholder`) will be returned.
+    """
+    items = (first_item,) + extra_items
+    for item in items:
+        if not isinstance(item, DefaultPlaceholder):
+            return item
+    return first_item