Skip to content

Commit 2596963

Browse files
authored
Merge pull request #123 from altendky/check_mypy
2 parents 013b307 + 04656a0 commit 2596963

File tree

4 files changed

+54
-19
lines changed

4 files changed

+54
-19
lines changed

.coveragerc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,24 @@ parallel = true
1414
show_missing = true
1515
precision = 2
1616
omit = *migrations*
17+
exclude_lines =
18+
# Lines matching these regexes don't need to be covered
19+
# https://coverage.readthedocs.io/en/coverage-5.5/excluding.html?highlight=exclude_lines#advanced-exclusion
20+
21+
# this is the default but must be explicitly specified since
22+
# we are overriding exclude_lines
23+
pragma: no cover
24+
25+
# abstract methods won't ever be run
26+
abc\.abstractmethod
27+
28+
# overloads won't ever be run
29+
typing\.overload
30+
31+
# ellipses (...) are often used in type-hint related stub code
32+
^\s*\.\.\.\s*$
33+
34+
# TYPE_CHECKING guarded code won't be run
35+
if typing.TYPE_CHECKING:
36+
if t.TYPE_CHECKING:
37+
if TYPE_CHECKING:

src/desert/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import desert._version
99

1010

11+
if t.TYPE_CHECKING:
12+
import attr._make
13+
14+
1115
def schema(
1216
cls: t.Type, many: bool = False, meta: t.Dict[str, t.Any] = {}
1317
) -> marshmallow.Schema:
@@ -63,7 +67,10 @@ class A:
6367
"""
6468
meta = metadata(marshmallow_field)
6569
meta.update(kw.pop("metadata", {}))
66-
return dataclasses.field(**kw, metadata=meta)
70+
# typeshed hints it as Mapping[str, Any] without any obvious reason
71+
# https://github.com/python/typeshed/blob/95a45eb4abd0c25849268983cb614e3bf6b9b264/stdlib/dataclasses.pyi#L81
72+
# https://github.com/python/typeshed/pull/5823
73+
return dataclasses.field(**kw, metadata=meta) # type: ignore[arg-type]
6774

6875

6976
def ib(marshmallow_field: marshmallow.fields.Field, **kw) -> attr._make._CountingAttr:

src/desert/_make.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ class User:
5454
Schema: t.ClassVar[Type[Schema]] = Schema # For the type checker
5555
"""
5656

57-
__all__ = ("schema_class", "schema")
58-
5957
import dataclasses
6058
import datetime
6159
import decimal
@@ -99,7 +97,7 @@ def class_schema(
9997
``marshmallow_field`` key in the metadata dictionary.
10098
"""
10199

102-
fields: t.Union[t.Tuple[dataclasses.Field], t.Tuple[attr.Attribute]]
100+
fields: t.Union[t.Tuple[dataclasses.Field, ...], t.Tuple[attr.Attribute, ...]]
103101

104102
if not isinstance(clazz, type):
105103
raise desert.exceptions.UnknownType(
@@ -118,12 +116,8 @@ def class_schema(
118116
else:
119117
raise desert.exceptions.NotAnAttrsClassOrDataclass(clazz)
120118

121-
# Copy all public fields of the dataclass to the schema
122-
attributes = {
123-
field.name: field for field in fields if not field.name.startswith("_")
124-
}
125-
126119
# Update the schema members to contain marshmallow fields instead of dataclass fields.
120+
attributes: t.Dict[str, marshmallow.fields.Field] = {}
127121
hints = t.get_type_hints(clazz)
128122
for field in fields:
129123
if field.init:
@@ -133,16 +127,23 @@ def class_schema(
133127
field.metadata,
134128
)
135129

130+
class_attributes: t.Dict[str, t.Any] = {
131+
**attributes,
132+
"Meta": type("Meta", (), meta),
133+
}
134+
136135
cls_schema = type(
137136
clazz.__name__,
138137
(_base_schema(clazz),),
139-
{**attributes, "Meta": type("Meta", (), meta)},
138+
class_attributes,
140139
)
141140

142141
return t.cast(t.Type[marshmallow.Schema], cls_schema)
143142

144143

145-
_native_to_marshmallow: t.Dict[type, t.Type[marshmallow.fields.Field]] = {
144+
_native_to_marshmallow: t.Dict[
145+
t.Union[type, t.Any], t.Type[marshmallow.fields.Field]
146+
] = {
146147
int: marshmallow.fields.Integer,
147148
float: marshmallow.fields.Float,
148149
str: marshmallow.fields.String,
@@ -171,7 +172,7 @@ def only(items: t.Iterable[T]) -> T:
171172

172173

173174
def field_for_schema(
174-
typ: type, default=marshmallow.missing, metadata: t.Mapping[str, t.Any] = None
175+
typ: type, default=marshmallow.missing, metadata: t.Mapping[t.Any, t.Any] = None
175176
) -> marshmallow.fields.Field:
176177
"""
177178
Get a marshmallow Field corresponding to the given python type.
@@ -319,25 +320,30 @@ def _get_field_default(field: t.Union[dataclasses.Field, attr.Attribute]):
319320
<marshmallow.missing>
320321
"""
321322
if isinstance(field, dataclasses.Field):
322-
if field.default_factory != dataclasses.MISSING:
323+
# https://github.com/python/mypy/issues/10750
324+
if field.default_factory != dataclasses.MISSING: # type: ignore[misc]
323325
return dataclasses.MISSING
324326
if field.default is dataclasses.MISSING:
325327
return marshmallow.missing
326328
return field.default
327329
elif isinstance(field, attr.Attribute):
328330
if field.default == attr.NOTHING:
329331
return marshmallow.missing
330-
if isinstance(field.default, attr.Factory):
331-
if field.default.takes_self:
332+
if isinstance(field.default, attr.Factory): # type: ignore[arg-type]
333+
# attrs specifically doesn't support this so as to support the
334+
# primary use case.
335+
# https://github.com/python-attrs/attrs/blob/38580632ceac1cd6e477db71e1d190a4130beed4/src/attr/__init__.pyi#L63-L65
336+
if field.default.takes_self: # type: ignore[union-attr]
332337
return attr.NOTHING
333-
return field.default.factory
338+
return field.default.factory # type: ignore[union-attr]
334339
return field.default
335340
else:
336341
raise TypeError(field)
337342

338343

339-
def sentinel(name):
340-
return attr.make_class(name, [], frozen=True)()
344+
@attr.frozen
345+
class _DesertSentinel:
346+
pass
341347

342348

343-
_DESERT_SENTINEL = sentinel("_DesertSentinel")
349+
_DESERT_SENTINEL = _DesertSentinel()

tox.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ commands =
4343
check-manifest {toxinidir}
4444
black --check {toxinidir}
4545
isort --verbose --check-only --diff src tests setup.py
46+
mypy src/desert/
4647

4748
[testenv:spell]
4849
setenv =

0 commit comments

Comments
 (0)