@@ -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-
5957import dataclasses
6058import datetime
6159import 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
173174def 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 ( )
0 commit comments