Basically, I am trying to define a subclass of string which conforms with the RFC UUID scheme. An object of this class can only exist if it conforms to the 8-4-4-4-12 hex string, else does not. So I need to check it during initialisation, but not sure how to account for all possible initialisation arguments of str
.
This is how my code looks like:
import uuid
class UniversalID(str):
def __init__(self, val:str):
super().__init__()
try:
uuid.UUID(hex=val)
self=val
except ValueError as inv_str:
logging.error(msg=f'Invalid id queried {val}')
raise inv_str
sample= uuid.uuid1().hex
isinstance(UniversalID(sample), str) # Shows true, as expected
But not sure if this is the right approach, as there may be other arguments of str
initialiser that I am not taking care of.
The question can be generalised to, if I want to modify the __init__
method with some validation check in the subclass, do I need to have total access to the initialiser in the base class, to make sure it accepts the same arguments and processes the same way? Worse still, do I have to, like, copy paste the code?
As I said in a comment you have to set the value of immutable types, like strings, in their __new__()
method. I couldn't find a canonical source or example for you — I know about it from some books I read long ago, so decided just to make up one for you (based on your code):
import logging
import uuid
class UniversalID(str):
# You don't really need to define this, because it's what would happen anyway.
def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs)
def __init__(self, *args, **kwargs):
try:
uuid.UUID(hex=self)
except ValueError as inv_str:
logging.error(msg=f'Invalid id queried {self}')
raise inv_str
if __name__ == '__main__':
sample1 = uuid.uuid1().hex
try:
isinstance(UniversalID(sample1), str)
except ValueError as exc:
print(f'ERROR: {exc} {sample1=!r}')
else:
print(f'{sample1=!r} is a valid hex uuid.')
print()
sample2 = 'not a hex uuid'
try:
isinstance(UniversalID(sample2), str)
except ValueError as exc:
print(f'ERROR: {exc} {sample2=!r}')
else:
print(f'{sample2=!r} is a valid hex uuid.')