I have the following dataclass:
@dataclass(frozen=True)
class Info:
client_id: str
purchase_id: str
Both these ids are supposed to be UUID's.
I have a method that can check if the arg is UUID:
from uuid import UUID
def check_uuid(arg):
try:
UUID(arg)
except ValueError:
raise argparse.ArgumentTypeError(f"'{arg}' is not a valid UUID")
return arg
I want to define a decorator that I can wrap around my dataclass to perform this check. Something like this:
@check_types
@dataclass(frozen=True)
class Info:
client_id: str
purchase_id: str
Here is what I wrote:
from functools import wraps
import argparse
import inspect
def check_types(callable):
def check_uuid(*args, **kwargs):
for arg in args[1:]
try:
UUID(arg)
except ValueError:
raise argparse.ArgumentTypeError(f"'{arg}' is not a valid UUID")
def decorate(func):
@wraps(func)
def wrapper(*args, **kwargs):
check_uuid(*args, **kwargs)
return func(*args, **kwargs)
return wrapper
if inspect.isclass(callable):
callable.__init__ = decorate(callable.__init__)
return callable
return decorate(callable)
but when I instantiate the class i = Info("123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174000")
I get the following error:
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
I am not sure what I am missing, alternatively, is there a better way I can be type checking for UUIDs when the class is instantiated?
If they are supposed to be UUIDs, then type them as such. The caller should be responsible for parsing any strings before instantiating Info.
@dataclass(frozen=True)
class Info:
client_id: UUID
purchase_id: UUID
x = "..."
y = "..."
i = Info(UUID(x), UUID(y))
You can help the caller by providing a class method that does the type conversion
@dataclass(frozen=True)
class Info:
client_id: UUID
purchase_id: UUID
@classmethod
def from_strings(cls, x, y):
# Let any ValueErrors speak for themselves
x = UUID(x)
y = UUID(y)
return cls(UUID(x), UUID(y))
x = "..."
y = "..."
i = Info.from_strings(x, y)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With