-
-
Save cstrap/ae84b612f0f7f2dd48da92d82bc8b0de to your computer and use it in GitHub Desktop.
Simple type checked objects in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
from type_checked_entities import entity_factory | |
Giraffe = entity_factory( # let's define what is a giraffe! | |
"giraffe", | |
name=str, # my name is a string | |
age=float, # my age is an int | |
eats=object, # I eat pretty much everything. | |
) | |
Giraffe.say_hi = lambda self: "the giraffe {} says hi!".format(self.name) # example property of a giraffe | |
Grass = entity_factory( | |
"grass", | |
color='green' | |
) | |
grass = Grass() | |
giraffe_1 = Giraffe( | |
name="Gira", | |
age=21, | |
eats=grass | |
) | |
giraffe_2 = Giraffe() | |
print giraffe_1.say_hi() # the giraffe Gira says hi! | |
try: | |
print giraffe_2.say_hi() # explicitly fails, giraffe_2.name needed for the method is still undefined | |
except ValueError as error: | |
print error | |
giraffe_2.name = "rhino" # whoa, didn't see this coming | |
giraffe_2.say_hi() | |
try: | |
giraffe_2.age = 11.5 | |
except TypeError as error: # 11.5 is not an valid int age | |
print error | |
giraffe_2.age = 11 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
__author__ = "Luca Giacomel" | |
__license__ = "Public Domain" | |
def generate_setter(field): | |
def setter(self, value): | |
field = setter.__name__[4:] | |
if isinstance(value, self.enforced_types[field]): | |
setattr(self, "_%s" % field, value) | |
else: | |
raise TypeError("%s object cannot have property %s with value \"%s\" (type: %s - it must be %s)" % ( | |
self.__class__, | |
field, | |
value, | |
type(value), | |
self.enforced_types[field])) | |
setter.__name__ = "set_%s" % field | |
return setter | |
def generate_getter(field): | |
def getter(self): | |
field = getter.__name__[4:] | |
if not hasattr(self, "_%s" % field): | |
raise ValueError("property %s of instance %s of object %s is undefined" % | |
(field, self.__repr__(), self.__class__)) | |
return getattr(self, "_%s" % field) | |
getter.__name__ = "set_%s" % field | |
return getter | |
def entity_factory(entity_type, **kwargs): | |
props = dict() | |
props['enforced_types'] = kwargs | |
for obj, _ in kwargs.items(): | |
props[obj] = property(generate_getter(obj), generate_setter(obj)) | |
def __init__(self, **kwargs): | |
for attr, tpe in kwargs.items(): | |
if attr in props['enforced_types'] and isinstance(attr, props['enforced_types'][attr]): | |
setattr(self, "_%s" % attr, tpe) | |
props['__init__'] = __init__ | |
cls = type( | |
entity_type, | |
(object,), | |
props | |
) | |
return cls |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment