minitraits.py
118 lines
| 3.2 KiB
| text/x-python
|
PythonLexer
/ sandbox / minitraits.py
Brian Granger
|
r1741 | import types | |
class AttributeBase(object): | |||
def __get__(self, inst, cls=None): | |||
if inst is None: | |||
return self | |||
try: | |||
return inst._attributes[self.name] | |||
except KeyError: | |||
raise AttributeError("object has no attribute %r" % self.name) | |||
def __set__(self, inst, value): | |||
actualValue = self.validate(inst, self.name, value) | |||
inst._attributes[self.name] = actualValue | |||
def validate(self, inst, name, value): | |||
raise NotImplementedError("validate must be implemented by a subclass") | |||
class NameFinder(type): | |||
def __new__(cls, name, bases, classdict): | |||
attributeList = [] | |||
for k,v in classdict.iteritems(): | |||
if isinstance(v, AttributeBase): | |||
v.name = k | |||
attributeList.append(k) | |||
classdict['_attributeList'] = attributeList | |||
return type.__new__(cls, name, bases, classdict) | |||
class HasAttributes(object): | |||
__metaclass__ = NameFinder | |||
def __init__(self): | |||
self._attributes = {} | |||
def getAttributeNames(self): | |||
return self._attributeList | |||
def getAttributesOfType(self, t, default=None): | |||
result = {} | |||
for a in self._attributeList: | |||
if self.__class__.__dict__[a].__class__ == t: | |||
try: | |||
value = getattr(self, a) | |||
except AttributeError: | |||
value = None | |||
result[a] = value | |||
return result | |||
class TypedAttribute(AttributeBase): | |||
def validate(self, inst, name, value): | |||
if type(value) != self._type: | |||
raise TypeError("attribute %s must be of type %s" % (name, self._type)) | |||
else: | |||
return value | |||
# class Option(TypedAttribute): | |||
# | |||
# _type = types.IntType | |||
# | |||
# class Param(TypedAttribute): | |||
# | |||
# _type = types.FloatType | |||
# | |||
# class String(TypedAttribute): | |||
# | |||
# _type = types.StringType | |||
class TypedSequenceAttribute(AttributeBase): | |||
def validate(self, inst, name, value): | |||
if type(value) != types.TupleType and type(value) != types.ListType: | |||
raise TypeError("attribute %s must be a list or tuple" % (name)) | |||
else: | |||
for item in value: | |||
if type(item) != self._subtype: | |||
raise TypeError("attribute %s must be a list or tuple of items with type %s" % (name, self._subtype)) | |||
return value | |||
# class Instance(AttributeBase): | |||
# | |||
# def __init__(self, cls): | |||
# self.cls = cls | |||
# | |||
# def validate(self, inst, name, value): | |||
# if not isinstance(value, self.cls): | |||
# raise TypeError("attribute %s must be an instance of class %s" % (name, self.cls)) | |||
# else: | |||
# return value | |||
# class OptVec(TypedSequenceAttribute): | |||
# | |||
# _subtype = types.IntType | |||
# | |||
# class PrmVec(TypedSequenceAttribute): | |||
# | |||
# _subtype = types.FloatType | |||
# | |||
# class StrVec(TypedSequenceAttribute): | |||
# | |||
# _subtype = types.StringType | |||
# | |||
# | |||
# class Bar(HasAttributes): | |||
# | |||
# a = Option() | |||
# | |||
# class Foo(HasAttributes): | |||
# | |||
# a = Option() | |||
# b = Param() | |||
# c = String() | |||
# d = OptVec() | |||
# e = PrmVec() | |||
# f = StrVec() | |||
# h = Instance(Bar) |