biqqles / dataclassy

A fast and flexible reimplementation of data classes
https://pypi.org/project/dataclassy
Mozilla Public License 2.0
82 stars 9 forks source link

pass custom metaclass to dataclass #4

Closed otistamp closed 4 years ago

otistamp commented 4 years ago

Is there a proposed way to define a dataclass with a custom metaclass? It seems like it would have to inherit from DataClassMeta and the signature of apply_metaclass takes the metaclass as a kwarg but the dataclass decorator doesn't pass along an option to override that. Currently, this is ignored:

@dataclass
class DataClass(metaclass=CustomMetaClass):
    prop: str
biqqles commented 4 years ago

Interesting idea. While your syntax would possibly be simpler to implement, I wonder if @dataclass(meta=CustomMetaClass) would be clearer, because this makes the fact that you are overriding dataclassy's metaclass (and therefore that the metaclass must be a suitable substitution for dataclassy's own) more intuitive and explicit.

I didn't really consider the possibility of someone wanting to mix in their own metaclasses. What sort of use case do you have in mind for this? (Wanting to automatically cache the class' methods is one such example I could think of.)

For now at least, you could perhaps make a dataclass a member of your custom metaclass-ed class, delegating the outer class' methods to it as necessary. Or, as a quick and dirty alternative, you could even monkey patch dataclassy.dataclass.DataClassMeta.

otistamp commented 4 years ago

My use case is for a schema wrapper around pymongo/motor which defines the collection and accessor class methods as properties. I tried using dataclasses, but because of the pitfalls it just didn't quite cut it. Currently I'm using pydantic but it is too aggressive with validation and I'd like to control when validation is run (ie only when unsafe payloads come from an http request and not when the data comes out of the db).

I'll play around with it and see what happens, thanks!

biqqles commented 4 years ago

As you can see this has now been implemented with a new meta option for @dataclass. Let me know if you find success "merging" the metaclasses - from experience it is often tricky but rewarding to get right!