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)66 if origin is Union or origin is UnionType:67 for arg in get_args(annotation):68 if field_annotation_is_sequence(arg):69 return True70 return False71 return _annotation_is_sequence(annotation) or _annotation_is_sequence(72 get_origin(annotation)73 )747576def value_is_sequence(value: Any) -> bool:77 return isinstance(value, sequence_types) and not isinstance(value, (str, bytes))787980def _annotation_is_complex(annotation: type[Any] | None) -> bool:81 return (82 lenient_issubclass(annotation, (BaseModel, Mapping, UploadFile))83 or _annotation_is_sequence(annotation)84 or is_dataclass(annotation)85 )868788def field_annotation_is_complex(annotation: type[Any] | None) -> bool:89 origin = get_origin(annotation)90 if origin is Union or origin is UnionType:91 return any(field_annotation_is_complex(arg) for arg in get_args(annotation))9293 if origin is Annotated:94 return field_annotation_is_complex(get_args(annotation)[0])9596 return (97 _annotation_is_complex(annotation)98 or _annotation_is_complex(origin)99 or hasattr(origin, "__pydantic_core_schema__")100 or hasattr(origin, "__get_pydantic_core_schema__")101 )102103104def field_annotation_is_scalar(annotation: Any) -> bool:105 # handle Ellipsis here to make tuple[int, ...] work nicely106 return annotation is Ellipsis or not field_annotation_is_complex(annotation)107108109def field_annotation_is_scalar_sequence(annotation: type[Any] | None) -> bool:110 origin = get_origin(annotation)111 if origin is Union or origin is UnionType:112 at_least_one_scalar_sequence = False113 for arg in get_args(annotation):114 if field_annotation_is_scalar_sequence(arg):115 at_least_one_scalar_sequence = True116 continue117 elif not field_annotation_is_scalar(arg):118 return False119 return at_least_one_scalar_sequence120 return field_annotation_is_sequence(annotation) and all(121 field_annotation_is_scalar(sub_annotation)122 for sub_annotation in get_args(annotation)123 )124125126def is_bytes_or_nonable_bytes_annotation(annotation: Any) -> bool:127 if lenient_issubclass(annotation, bytes):128 return True129 origin = get_origin(annotation)130 if origin is Union or origin is UnionType:131 for arg in get_args(annotation):132 if lenient_issubclass(arg, bytes):133 return True134 return False135136137def is_uploadfile_or_nonable_uploadfile_annotation(annotation: Any) -> bool:138 if lenient_issubclass(annotation, UploadFile):139 return True140 origin = get_origin(annotation)141 if origin is Union or origin is UnionType:142 for arg in get_args(annotation):143 if lenient_issubclass(arg, UploadFile):144 return True145 return False146147148def is_bytes_sequence_annotation(annotation: Any) -> bool:149 origin = get_origin(annotation)150 if origin is Union or origin is UnionType:151 at_least_one = False152 for arg in get_args(annotation):153 if is_bytes_sequence_annotation(arg):154 at_least_one = True155 continue156 return at_least_one157 return field_annotation_is_sequence(annotation) and all(158 is_bytes_or_nonable_bytes_annotation(sub_annotation)159 for sub_annotation in get_args(annotation)160 )161162163def is_uploadfile_sequence_annotation(annotation: Any) -> bool:164 origin = get_origin(annotation)165 if origin is Union or origin is UnionType:166 at_least_one = False167 for arg in get_args(annotation):168 if is_uploadfile_sequence_annotation(arg):169 at_least_one = True170 continue171 return at_least_one172 return field_annotation_is_sequence(annotation) and all(173 is_uploadfile_or_nonable_uploadfile_annotation(sub_annotation)174 for sub_annotation in get_args(annotation)175 )176177178def is_pydantic_v1_model_instance(obj: Any) -> bool:179 # TODO: remove this function once the required version of Pydantic fully180 # removes pydantic.v1181 try:182 with warnings.catch_warnings():183 warnings.simplefilter("ignore", UserWarning)184 from pydantic import v1185 except ImportError: # pragma: no cover186 return False187 return isinstance(obj, v1.BaseModel)188189190def is_pydantic_v1_model_class(cls: Any) -> bool:191 # TODO: remove this function once the required version of Pydantic fully192 # removes pydantic.v1193 try:194 with warnings.catch_warnings():195 warnings.simplefilter("ignore", UserWarning)196 from pydantic import v1197 except ImportError: # pragma: no cover198 return False199 return lenient_issubclass(cls, v1.BaseModel)200201202def annotation_is_pydantic_v1(annotation: Any) -> bool:203 if is_pydantic_v1_model_class(annotation):204 return True205 origin = get_origin(annotation)206 if origin is Union or origin is UnionType:207 for arg in get_args(annotation):208 if is_pydantic_v1_model_class(arg):209 return True210 if field_annotation_is_sequence(annotation):211 for sub_annotation in get_args(annotation):212 if annotation_is_pydantic_v1(sub_annotation):213 return True214 return False
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.