Ensure functions have docstrings for documentation
def lenient_issubclass(
1import types2import typing3import warnings4from collections import deque5from collections.abc import Mapping, Sequence6from dataclasses import is_dataclass7from typing import (8 Annotated,9 Any,10 TypeGuard,11 TypeVar,12 Union,13 get_args,14 get_origin,15)1617from fastapi.types import UnionType18from pydantic import BaseModel19from pydantic.version import VERSION as PYDANTIC_VERSION20from starlette.datastructures import UploadFile2122_T = TypeVar("_T")2324# Copy from Pydantic: pydantic/_internal/_typing_extra.py25WithArgsTypes: tuple[Any, ...] = (26 typing._GenericAlias, # type: ignore[attr-defined] # ty: ignore[unresolved-attribute]27 types.GenericAlias,28 types.UnionType,29) # pyright: ignore[reportAttributeAccessIssue]3031PYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(".")[:2])323334sequence_annotation_to_type = {35 Sequence: list,36 list: list,37 tuple: tuple,38 set: set,39 frozenset: frozenset,40 deque: deque,41}4243sequence_types: tuple[type[Any], ...] = tuple(sequence_annotation_to_type.keys())444546# Copy of Pydantic: pydantic/_internal/_utils.py with added TypeGuard47def lenient_issubclass(48 cls: Any, class_or_tuple: type[_T] | tuple[type[_T], ...] | None49) -> TypeGuard[type[_T]]:50 try:51 return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type] # ty: ignore[invalid-argument-type]52 except TypeError: # pragma: no cover53 if isinstance(cls, WithArgsTypes):54 return False55 raise # pragma: no cover565758def _annotation_is_sequence(annotation: type[Any] | None) -> bool:59 if lenient_issubclass(annotation, (str, bytes)):60 return False61 return lenient_issubclass(annotation, sequence_types)626364def field_annotation_is_sequence(annotation: type[Any] | None) -> bool:65 origin = get_origin(annotation)6667 if origin is Annotated:68 return field_annotation_is_sequence(get_args(annotation)[0])6970 if origin is Union or origin is UnionType:71 for arg in get_args(annotation):72 if field_annotation_is_sequence(arg):73 return True74 return False75 return _annotation_is_sequence(annotation) or _annotation_is_sequence(76 get_origin(annotation)77 )787980def value_is_sequence(value: Any) -> bool:81 return isinstance(value, sequence_types) and not isinstance(value, (str, bytes))828384def _annotation_is_complex(annotation: type[Any] | None) -> bool:85 return (86 lenient_issubclass(annotation, (BaseModel, Mapping, UploadFile))87 or _annotation_is_sequence(annotation)88 or is_dataclass(annotation)89 )909192def field_annotation_is_complex(annotation: type[Any] | None) -> bool:93 origin = get_origin(annotation)94 if origin is Union or origin is UnionType:95 return any(field_annotation_is_complex(arg) for arg in get_args(annotation))9697 if origin is Annotated:98 return field_annotation_is_complex(get_args(annotation)[0])99100 return (101 _annotation_is_complex(annotation)102 or _annotation_is_complex(origin)103 or hasattr(origin, "__pydantic_core_schema__")104 or hasattr(origin, "__get_pydantic_core_schema__")105 )106107108def field_annotation_is_scalar(annotation: Any) -> bool:109 # handle Ellipsis here to make tuple[int, ...] work nicely110 return annotation is Ellipsis or not field_annotation_is_complex(annotation)111112113def field_annotation_is_scalar_sequence(annotation: type[Any] | None) -> bool:114 origin = get_origin(annotation)115116 if origin is Annotated:117 return field_annotation_is_scalar_sequence(get_args(annotation)[0])118119 if origin is Union or origin is UnionType:120 at_least_one_scalar_sequence = False121 for arg in get_args(annotation):122 if field_annotation_is_scalar_sequence(arg):123 at_least_one_scalar_sequence = True124 continue125 elif not field_annotation_is_scalar(arg):126 return False127 return at_least_one_scalar_sequence128 return field_annotation_is_sequence(annotation) and all(129 field_annotation_is_scalar(sub_annotation)130 for sub_annotation in get_args(annotation)131 )132133134def is_bytes_or_nonable_bytes_annotation(annotation: Any) -> bool:135 if lenient_issubclass(annotation, bytes):136 return True137 origin = get_origin(annotation)138 if origin is Union or origin is UnionType:139 for arg in get_args(annotation):140 if lenient_issubclass(arg, bytes):141 return True142 return False143144145def is_uploadfile_or_nonable_uploadfile_annotation(annotation: Any) -> bool:146 if lenient_issubclass(annotation, UploadFile):147 return True148 origin = get_origin(annotation)149 if origin is Union or origin is UnionType:150 for arg in get_args(annotation):151 if lenient_issubclass(arg, UploadFile):152 return True153 return False154155156def is_bytes_sequence_annotation(annotation: Any) -> bool:157 origin = get_origin(annotation)158 if origin is Union or origin is UnionType:159 at_least_one = False160 for arg in get_args(annotation):161 if is_bytes_sequence_annotation(arg):162 at_least_one = True163 continue164 return at_least_one165 return field_annotation_is_sequence(annotation) and all(166 is_bytes_or_nonable_bytes_annotation(sub_annotation)167 for sub_annotation in get_args(annotation)168 )169170171def is_uploadfile_sequence_annotation(annotation: Any) -> bool:172 origin = get_origin(annotation)173 if origin is Union or origin is UnionType:174 at_least_one = False175 for arg in get_args(annotation):176 if is_uploadfile_sequence_annotation(arg):177 at_least_one = True178 continue179 return at_least_one180 return field_annotation_is_sequence(annotation) and all(181 is_uploadfile_or_nonable_uploadfile_annotation(sub_annotation)182 for sub_annotation in get_args(annotation)183 )184185186def is_pydantic_v1_model_instance(obj: Any) -> bool:187 # TODO: remove this function once the required version of Pydantic fully188 # removes pydantic.v1189 try:190 with warnings.catch_warnings():191 warnings.simplefilter("ignore", UserWarning)192 from pydantic import v1193 except ImportError: # pragma: no cover194 return False195 return isinstance(obj, v1.BaseModel)196197198def is_pydantic_v1_model_class(cls: Any) -> bool:199 # TODO: remove this function once the required version of Pydantic fully200 # removes pydantic.v1201 try:202 with warnings.catch_warnings():203 warnings.simplefilter("ignore", UserWarning)204 from pydantic import v1205 except ImportError: # pragma: no cover206 return False207 return lenient_issubclass(cls, v1.BaseModel)208209210def annotation_is_pydantic_v1(annotation: Any) -> bool:211 if is_pydantic_v1_model_class(annotation):212 return True213 origin = get_origin(annotation)214 if origin is Union or origin is UnionType:215 for arg in get_args(annotation):216 if is_pydantic_v1_model_class(arg):217 return True218 if field_annotation_is_sequence(annotation):219 for sub_annotation in get_args(annotation):220 if annotation_is_pydantic_v1(sub_annotation):221 return True222 return False
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.
Generated by searchcode.com · powered by code_get_file + code_get_findings