Skip to content

Instantly share code, notes, and snippets.

@palankai
Created February 11, 2016 08:05
Show Gist options
  • Save palankai/389ad1519335a241a9cc to your computer and use it in GitHub Desktop.
Save palankai/389ad1519335a241a9cc to your computer and use it in GitHub Desktop.
Declarative class attributes
class Descriptor:
def __get__(self, instance, cls):
if instance is None:
return self
return instance.__dict__.get(self.name)
def bind(self, name):
self.name = name
class Typed(Descriptor):
def __init__(self, expected):
self.expected = expected
def __set__(self, instance, value):
if value is not None and not isinstance(value, self.expected):
raise TypeError('expected: %s' % self.expected.__name__)
instance.__dict__[self.name] = value
def declarative(cls):
for name, field in cls.__dict__.items():
if isinstance(field, Descriptor):
field.bind(name)
return cls
# example
class PositiveNumber(Declarative):
def __set__(self, instance, value):
if value is not None:
if not isinstance(value, [int, float]):
raise TypeError('expected: %s' % self.expected.__name__)
if value <= 0:
raise ValueError('expected: positive number')
instance.__dict__[self.name] = value
@declarative
class Role:
id = Typed(int)
name = Typed(str)
@declarative
class DemoClass:
id = Typed(int)
created_at = Typed(datetime)
guid = Typed(uuid.UUID)
username = Typed(str)
password = Typed(str)
role = Typed(Role)
groups = Typed(list)
height = PositiveNumber()
# With this descriptor you can create simple type validated data models
# It could help to make readable classes and avoid basic pitfalls
# However it isn't really for value validation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment