-
Notifications
You must be signed in to change notification settings - Fork 76
add slots, match_args, kw_only to dataclass func #252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -103,6 +103,9 @@ def dataclass( | |
order: bool = False, | ||
unsafe_hash: bool = False, | ||
frozen: bool = False, | ||
match_args: bool = True, | ||
kw_only: bool = False, | ||
slots: bool = False, | ||
base_schema: Optional[Type[marshmallow.Schema]] = None, | ||
cls_frame: Optional[types.FrameType] = None, | ||
) -> Type[_U]: | ||
|
@@ -117,6 +120,9 @@ def dataclass( | |
order: bool = False, | ||
unsafe_hash: bool = False, | ||
frozen: bool = False, | ||
match_args: bool = True, | ||
kw_only: bool = False, | ||
slots: bool = False, | ||
base_schema: Optional[Type[marshmallow.Schema]] = None, | ||
cls_frame: Optional[types.FrameType] = None, | ||
) -> Callable[[Type[_U]], Type[_U]]: | ||
|
@@ -135,6 +141,9 @@ def dataclass( | |
order: bool = False, | ||
unsafe_hash: bool = False, | ||
frozen: bool = False, | ||
match_args: bool = True, | ||
kw_only: bool = False, | ||
slots: bool = False, | ||
base_schema: Optional[Type[marshmallow.Schema]] = None, | ||
cls_frame: Optional[types.FrameType] = None, | ||
) -> Union[Type[_U], Callable[[Type[_U]], Type[_U]]]: | ||
|
@@ -163,10 +172,46 @@ def dataclass( | |
>>> Point.Schema().load({'x':0, 'y':0}) # This line can be statically type checked | ||
Point(x=0.0, y=0.0) | ||
""" | ||
# dataclass's typing doesn't expect it to be called as a function, so ignore type check | ||
dc = dataclasses.dataclass( # type: ignore | ||
_cls, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen | ||
) | ||
# Check python version for dataclass params only available for python >= 3.10. | ||
# If python version is below 3.10 and any of these params are set to anything | ||
# other than their default, raise ValueError | ||
if sys.version_info >= (3, 10): | ||
# dataclass's typing doesn't expect it to be called as a function, so ignore type check | ||
dc = dataclasses.dataclass( # type: ignore | ||
_cls, | ||
repr=repr, | ||
eq=eq, | ||
order=order, | ||
unsafe_hash=unsafe_hash, | ||
frozen=frozen, | ||
match_args=match_args, | ||
kw_only=kw_only, | ||
slots=slots, | ||
) | ||
else: | ||
args = { | ||
"match_args": { | ||
"error_message": "'match_args' argument is only available for python >= 3.10", | ||
"default_value": True, | ||
}, | ||
"kw_only": { | ||
"error_message": "'kw_only' argument is only available for python >= 3.10", | ||
"default_value": False, | ||
}, | ||
"slots": { | ||
"error_message": "'slots' argument is only available for python >= 3.10", | ||
"default_value": False, | ||
}, | ||
} | ||
|
||
for arg, arg_info in args.items(): | ||
if locals()[arg] is not arg_info["default_value"]: | ||
raise ValueError(arg_info["error_message"]) | ||
|
||
# dataclass's typing doesn't expect it to be called as a function, so ignore type check | ||
dc = dataclasses.dataclass( # type: ignore | ||
_cls, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen | ||
) | ||
Comment on lines
+192
to
+214
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why this ? Can't we just forward the arguments we got to the base dataclass implementation, and let it error if it wants to ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree. For the implementation can we not just do def dataclass(
__cls: Optional[Type[_U]] = None,
*,
base_schema: Optional[Type[marshmallow.Schema]] = None,
cls_frame: Optional[types.FrameType] = None,
**kwargs: bool,
) -> Union[Type[_U], Callable[[Type[_U]], Type[_U]]]:
dc = dataclasses.dataclass(**kwargs)
if not cls_frame:
current_frame = inspect.currentframe()
if current_frame:
cls_frame = current_frame.f_back
# Per https://docs.python.org/3/library/inspect.html#the-interpreter-stack
del current_frame
def decorate(cls: Type[_U]) -> Type[_U]:
return add_schema(dc(cls), base_schema, cls_frame=cls_frame)
if _cls is None:
return decorate
return decorate(cls) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This breaks the type signature. |
||
if not cls_frame: | ||
current_frame = inspect.currentframe() | ||
if current_frame: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel these overloads should be conditional on python version. I.e. The prototypes should not declare unsupported options.
Since (I think) we want
marshmallow_dataclass.dataclass
to have the same signature asdataclasses.dataclass
, we should probably just copy typeshed's interface definition fordataclass
.https://github.com/python/typeshed/blob/8b9b0f4d031fe614a0211e1faadf57b3340e643e/stdlib/dataclasses.pyi#L57C1-L104C1.