rnag/dataclass-wizard

Ability to add a custom type hook for unsupported builtin types like Path and re.Pattern

TomHodson opened this issue · 4 comments

  • Dataclass Wizard version: 0.22.2
  • Python version: 3.11.3
  • Operating System: OSX 12.3

Description

I wanted to create a type hook for re.Pattern following the example given here

What I Did

Copied the code from the link above and adapted it to my use case. However the example does two cases:

  1. Overrides the loader/dumper for a known type str
  2. Creates a loader for a custom class MyEnum

I would like to create a loader for a builtin class re.compile. I see someone has a pull request open for adding a loader for pathlib.Path but I don't see that you should have to support loaders for every single builtin class. So I would like to just do it myself.

After digging around in the code I got it to work by calling MyClass.register_load_hook(Pattern, MyClass.load_to_pattern). My question is: Is that the intended way this would work? If so I would be happy to open a pull request to update the docs to mention this. Otherwise it would be very cool some fancy introspection could make the call to register_load_hook happen automatically.

Love this library by the way!

Example Code:

from dataclasses import dataclass
from dataclass_wizard import JSONSerializable, DumpMixin, LoadMixin

import re
from re import Pattern

@dataclass
class MyClass(JSONSerializable, LoadMixin, DumpMixin):
    regex: Pattern
    my_str: str

    @staticmethod
    def load_to_str(o: str, *_) -> str:
        return o.upper()
    
    @staticmethod
    def load_to_pattern(o: Pattern, *_) -> Pattern:
        return re.compile(o)
    
# This line was not obvious to me from reading the docs
MyClass.register_load_hook(Pattern, MyClass.load_to_pattern)

data = {"my_str": "my string", "regex" : "[^/]+"}

c = MyClass.from_dict(data)
print(repr(c))
# prints:
#   MyClass(regex=re.compile('[^/]+'), my_str='MY STRING')

I addition I now realised that the register_load_hook solution does not apply recursively. I tried subclassing LoadMixin and/or replacing setup_default_loader but couldn't get it to apply recursively. Do you recommend a way to do this?

Any Update on this? I am currently tyring to do a similar thing. I storing physical units from the library pint in a dataclass and want to load and dump these.

Thanks for the working example, @TomHodson - saved my day