chore: more mypy checks (ollama, vllm, ...) (#1777)

# What does this PR do?

- **chore: mypy for strong_typing**
- **chore: mypy for remote::vllm**
- **chore: mypy for remote::ollama**
- **chore: mypy for providers.datatype**

---------

Signed-off-by: Ihar Hrachyshka <ihar.hrachyshka@gmail.com>
This commit is contained in:
Ihar Hrachyshka 2025-04-01 11:12:39 -04:00 committed by GitHub
parent d5e0f32485
commit 66d6c2580e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 103 additions and 72 deletions

View file

@ -77,7 +77,9 @@ def typeannotation(
"""
def wrap(cls: Type[T]) -> Type[T]:
cls.__repr__ = _compact_dataclass_repr
# mypy fails to equate bound-y functions (first argument interpreted as
# the bound object) with class methods, hence the `ignore` directive.
cls.__repr__ = _compact_dataclass_repr # type: ignore[method-assign]
if not dataclasses.is_dataclass(cls):
cls = dataclasses.dataclass( # type: ignore[call-overload]
cls,

View file

@ -627,7 +627,8 @@ class NamedTupleDeserializer(ClassDeserializer[NamedTuple]):
super().assign(property_parsers)
def create(self, **field_values: Any) -> NamedTuple:
return self.class_type(**field_values)
# mypy fails to deduce that this class returns NamedTuples only, hence the `ignore` directive
return self.class_type(**field_values) # type: ignore[no-any-return]
class DataclassDeserializer(ClassDeserializer[T]):

View file

@ -48,7 +48,7 @@ class DocstringParam:
name: str
description: str
param_type: type = inspect.Signature.empty
param_type: type | str = inspect.Signature.empty
def __str__(self) -> str:
return f":param {self.name}: {self.description}"

View file

@ -260,7 +260,8 @@ def extend_enum(
values: Dict[str, Any] = {}
values.update((e.name, e.value) for e in source)
values.update((e.name, e.value) for e in extend)
enum_class: Type[enum.Enum] = enum.Enum(extend.__name__, values) # type: ignore
# mypy fails to determine that __name__ is always a string; hence the `ignore` directive.
enum_class: Type[enum.Enum] = enum.Enum(extend.__name__, values) # type: ignore[misc]
# assign the newly created type to the same module where the extending class is defined
enum_class.__module__ = extend.__module__
@ -327,9 +328,7 @@ def _unwrap_optional_type(typ: Type[Optional[T]]) -> Type[T]:
raise TypeError("optional type must have un-subscripted type of Union")
# will automatically unwrap Union[T] into T
return Union[
tuple(filter(lambda item: item is not type(None), typing.get_args(typ))) # type: ignore
]
return Union[tuple(filter(lambda item: item is not type(None), typing.get_args(typ)))] # type: ignore[return-value]
def is_type_union(typ: object) -> bool:
@ -431,7 +430,7 @@ def _unwrap_generic_list(typ: Type[List[T]]) -> Type[T]:
"Extracts the item type of a list type (e.g. returns `T` for `List[T]`)."
(list_type,) = typing.get_args(typ) # unpack single tuple element
return list_type
return list_type # type: ignore[no-any-return]
def is_generic_set(typ: object) -> TypeGuard[Type[set]]:
@ -456,7 +455,7 @@ def _unwrap_generic_set(typ: Type[Set[T]]) -> Type[T]:
"Extracts the item type of a set type (e.g. returns `T` for `Set[T]`)."
(set_type,) = typing.get_args(typ) # unpack single tuple element
return set_type
return set_type # type: ignore[no-any-return]
def is_generic_dict(typ: object) -> TypeGuard[Type[dict]]:
@ -513,7 +512,7 @@ def unwrap_annotated_type(typ: T) -> T:
if is_type_annotated(typ):
# type is Annotated[T, ...]
return typing.get_args(typ)[0]
return typing.get_args(typ)[0] # type: ignore[no-any-return]
else:
# type is a regular type
return typ
@ -538,7 +537,7 @@ def rewrap_annotated_type(transform: Callable[[Type[S]], Type[T]], typ: Type[S])
transformed_type = transform(inner_type)
if metadata is not None:
return Annotated[(transformed_type, *metadata)] # type: ignore
return Annotated[(transformed_type, *metadata)] # type: ignore[return-value]
else:
return transformed_type
@ -563,7 +562,7 @@ else:
return typing.get_type_hints(typ)
def get_class_properties(typ: type) -> Iterable[Tuple[str, type]]:
def get_class_properties(typ: type) -> Iterable[Tuple[str, type | str]]:
"Returns all properties of a class."
if is_dataclass_type(typ):
@ -573,7 +572,7 @@ def get_class_properties(typ: type) -> Iterable[Tuple[str, type]]:
return resolved_hints.items()
def get_class_property(typ: type, name: str) -> Optional[type]:
def get_class_property(typ: type, name: str) -> Optional[type | str]:
"Looks up the annotated type of a property in a class by its property name."
for property_name, property_type in get_class_properties(typ):

View file

@ -460,13 +460,17 @@ class JsonSchemaGenerator:
discriminator = None
if typing.get_origin(data_type) is Annotated:
discriminator = typing.get_args(data_type)[1].discriminator
ret = {"oneOf": [self.type_to_schema(union_type) for union_type in typing.get_args(typ)]}
ret: Schema = {"oneOf": [self.type_to_schema(union_type) for union_type in typing.get_args(typ)]}
if discriminator:
# for each union type, we need to read the value of the discriminator
mapping = {}
mapping: dict[str, JsonType] = {}
for union_type in typing.get_args(typ):
props = self.type_to_schema(union_type, force_expand=True)["properties"]
mapping[props[discriminator]["default"]] = self.type_to_schema(union_type)["$ref"]
# mypy is confused here because JsonType allows multiple types, some of them
# not indexable (bool?) or not indexable by string (list?). The correctness of
# types depends on correct model definitions. Hence multiple ignore statements below.
discriminator_value = props[discriminator]["default"] # type: ignore[index,call-overload]
mapping[discriminator_value] = self.type_to_schema(union_type)["$ref"] # type: ignore[index]
ret["discriminator"] = {
"propertyName": discriminator,

View file

@ -134,7 +134,10 @@ class IPv6Serializer(Serializer[ipaddress.IPv6Address]):
class EnumSerializer(Serializer[enum.Enum]):
def generate(self, obj: enum.Enum) -> Union[int, str]:
return obj.value
value = obj.value
if isinstance(value, int):
return value
return str(value)
class UntypedListSerializer(Serializer[list]):