Skip to content

Commit f27a41a

Browse files
authored
Merge pull request #406 from yukinarit/fix-mypy-core
Fix mypy/pyright errors in serde/core.py
2 parents 459d90a + e6811ca commit f27a41a

File tree

5 files changed

+42
-29
lines changed

5 files changed

+42
-29
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,14 @@ line_length = 100
8888

8989
[tool.pyright]
9090
include = ["examples", "serde/json.py", "serde/msgpack.py", "serde/toml.py", "serde/yaml.py", "serde/pickle.py"]
91-
exclude = ["serde/core.py", "serde/se.py", "serde/de.py", "serde/numpy.py", "bench", "tests", "serde/__init__.py"]
91+
exclude = ["serde/se.py", "serde/de.py", "serde/numpy.py", "bench", "tests", "serde/__init__.py"]
9292
pythonVersion = "3.11"
9393
reportMissingImports = false
9494

9595
[tool.mypy]
9696
strict = true
9797
ignore_missing_imports = true
98-
exclude = ["serde/core.py", "serde/se.py", "serde/de.py", "serde/numpy.py", "bench", "tests"]
98+
exclude = ["serde/se.py", "serde/de.py", "serde/numpy.py", "bench", "tests"]
9999

100100
[tool.ruff]
101101
select = [

serde/compat.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040
else:
4141
Literal = typing.Literal
4242

43+
# Create alias for `dataclasses.Field` because `dataclasses.Field` is a generic
44+
# class since 3.9 but is not in 3.7 and 3.8.
45+
if sys.version_info[:2] <= (3, 8):
46+
DataclassField = dataclasses.Field
47+
else:
48+
DataclassField = dataclasses.Field[Any]
49+
4350
try:
4451
if sys.version_info[:2] <= (3, 8):
4552
import numpy as np

serde/core.py

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,21 @@
1313
Callable,
1414
Dict,
1515
List,
16-
Mapping,
1716
Optional,
1817
Union,
1918
Generic,
2019
TypeVar,
2120
Tuple,
2221
overload,
22+
Mapping,
2323
)
2424

2525
import casefy
2626
import jinja2
2727
from typing_extensions import Type, get_type_hints
2828

2929
from .compat import (
30+
DataclassField,
3031
T,
3132
SerdeError,
3233
dataclass_fields,
@@ -344,7 +345,7 @@ def add_func(serde_scope: Scope, func_name: str, func_code: str, globals: Dict[s
344345
serde_scope.code[func_name] = code
345346

346347

347-
def is_instance(obj: Any, typ: Type[Any]) -> bool:
348+
def is_instance(obj: Any, typ: Any) -> bool:
348349
"""
349350
Type check function that works like `isinstance` but it accepts
350351
Subscripted Generics e.g. `List[int]`.
@@ -372,10 +373,13 @@ def is_instance(obj: Any, typ: Type[Any]) -> bool:
372373
elif is_generic(typ):
373374
return is_generic_instance(obj, typ)
374375
elif is_literal(typ):
375-
return True # TODO
376+
return True
376377
elif is_new_type_primitive(typ):
377-
inner = typ.__supertype__
378-
return isinstance(obj, inner)
378+
inner = getattr(typ, "__supertype__", None)
379+
if type(inner) is type:
380+
return isinstance(obj, inner)
381+
else:
382+
return False
379383
elif typ is Ellipsis:
380384
return True
381385
else:
@@ -460,13 +464,13 @@ class Func:
460464
multiple fields receives `skip_if` attribute.
461465
"""
462466

463-
inner: Callable
467+
inner: Callable[[Any], Any]
464468
""" Function to wrap in """
465469

466470
mangeld: str = ""
467471
""" Mangled function name """
468472

469-
def __call__(self, v):
473+
def __call__(self, v: Any) -> None:
470474
return self.inner(v) # type: ignore
471475

472476
@property
@@ -477,12 +481,12 @@ def name(self) -> str:
477481
return self.mangeld
478482

479483

480-
def skip_if_false(v):
484+
def skip_if_false(v: Any) -> Any:
481485
return not bool(v)
482486

483487

484-
def skip_if_default(v, default=None):
485-
return v == default
488+
def skip_if_default(v: Any, default: Optional[Any] = None) -> Any:
489+
return v == default # Why return type is deduced to be Any?
486490

487491

488492
@dataclass
@@ -493,19 +497,19 @@ class FlattenOpts:
493497

494498

495499
def field(
496-
*args,
500+
*args: Any,
497501
rename: Optional[str] = None,
498502
alias: Optional[List[str]] = None,
499503
skip: Optional[bool] = None,
500-
skip_if: Optional[Callable] = None,
504+
skip_if: Optional[Callable[[Any], Any]] = None,
501505
skip_if_false: Optional[bool] = None,
502506
skip_if_default: Optional[bool] = None,
503-
serializer=None,
504-
deserializer=None,
507+
serializer: Optional[Callable[..., Any]] = None,
508+
deserializer: Optional[Callable[..., Any]] = None,
505509
flatten: Optional[Union[FlattenOpts, bool]] = None,
506-
metadata=None,
507-
**kwargs,
508-
):
510+
metadata: Optional[Dict[str, Any]] = None,
511+
**kwargs: Any,
512+
) -> Any:
509513
"""
510514
Declare a field with parameters.
511515
"""
@@ -557,6 +561,7 @@ class Field(Generic[T]):
557561
hash: Any = field(default_factory=dataclasses._MISSING_TYPE)
558562
compare: Any = field(default_factory=dataclasses._MISSING_TYPE)
559563
metadata: Mapping[str, Any] = field(default_factory=dict)
564+
kw_only: bool = False
560565
case: Optional[str] = None
561566
alias: List[str] = field(default_factory=list)
562567
rename: Optional[str] = None
@@ -571,9 +576,7 @@ class Field(Generic[T]):
571576
type_args: Optional[List[str]] = None
572577

573578
@classmethod
574-
def from_dataclass(
575-
cls: Type[T], f: dataclasses.Field, parent: Optional[Type[Any]] = None
576-
) -> Field[T]:
579+
def from_dataclass(cls, f: DataclassField, parent: Optional[Type[Any]] = None) -> Field[T]:
577580
"""
578581
Create `Field` object from `dataclasses.Field`.
579582
"""
@@ -626,7 +629,7 @@ def from_dataclass(
626629
parent=parent,
627630
)
628631

629-
def to_dataclass(self) -> dataclasses.Field:
632+
def to_dataclass(self) -> DataclassField:
630633
f = dataclasses.Field(
631634
default=self.default,
632635
default_factory=self.default_factory,
@@ -635,6 +638,7 @@ def to_dataclass(self) -> dataclasses.Field:
635638
hash=self.hash,
636639
compare=self.compare,
637640
metadata=self.metadata,
641+
kw_only=self.kw_only,
638642
)
639643
assert self.name
640644
f.name = self.name
@@ -649,7 +653,7 @@ def is_self_referencing(self) -> bool:
649653
return self.type == self.parent
650654

651655
@staticmethod
652-
def mangle(field: Field[T], name: str) -> str:
656+
def mangle(field: DataclassField, name: str) -> str:
653657
"""
654658
Get mangled name based on field name.
655659
"""
@@ -781,13 +785,13 @@ def produce_unique_class_name(self) -> str:
781785
wrapper dataclass and stored in `Cache`.
782786
"""
783787
if self.is_internal():
784-
tag = casefy.pascalcase(self.tag)
788+
tag = casefy.pascalcase(self.tag) # type: ignore
785789
if not tag:
786790
raise SerdeError('"tag" must be specified in InternalTagging')
787791
return f"Internal{tag}"
788792
elif self.is_adjacent():
789-
tag = casefy.pascalcase(self.tag)
790-
content = casefy.pascalcase(self.content)
793+
tag = casefy.pascalcase(self.tag) # type: ignore
794+
content = casefy.pascalcase(self.content) # type: ignore
791795
if not tag:
792796
raise SerdeError('"tag" must be specified in AdjacentTagging')
793797
if not content:

serde/de.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@
9191

9292
__all__ = ["deserialize", "is_deserializable", "from_dict", "from_tuple"]
9393

94-
# Interface of Custom deserialize function.
94+
9595
DeserializeFunc = Callable[[Type[Any], Any], Any]
96+
""" Interface of Custom deserialize function. """
9697

9798

9899
def serde_custom_class_deserializer(

serde/se.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,9 @@
8383

8484
__all__ = ["serialize", "is_serializable", "to_dict", "to_tuple"]
8585

86-
# Interface of Custom serialize function.
86+
8787
SerializeFunc = Callable[[Type[Any], Any], Any]
88+
""" Interface of Custom serialize function. """
8889

8990

9091
def default_serializer(_cls: Type[Any], obj):

0 commit comments

Comments
 (0)