0001from ohm.validators import JSONConverter, LineConverter
0002
0003def simple_repr(func_name, *args, **kw):
0004 """
0005 Helper function for reprs like 'func_name(args, keywords)'
0006 """
0007 args = [repr(x) for x in args]
0008 args.extend(['%s=%r' % (name, value)
0009 for name, value in sorted(kw.items())])
0010 return '%s(%s)' % (func_name, ', '.join(args))
0011
0012class cache(object):
0013
0014 """
0015 A caching descriptor wrapper. Takes the attribute name and the
0016 wrapped descriptor as arguments.
0017
0018 To expire, use ``MyClass.cached_attr.expire(my_object)`` where
0019 ``my_object`` is an instance of ``MyClass``.
0020 """
0021
0022 def __init__(self, name, getter):
0023 self.name = name
0024 self._attr_name = '_cache_%s' % name
0025 self.getter = getter
0026
0027 def __get__(self, obj, type=None):
0028 if obj is None:
0029 return self
0030 try:
0031 return getattr(obj, self._attr_name)
0032 except AttributeError:
0033 pass
0034 value = self.getter.__get__(obj, type)
0035 setattr(obj, self._attr_name, value)
0036 return value
0037
0038 def __set__(self, obj, value):
0039 self.getter.__set__(obj, value)
0040 setattr(obj, self._attr_name, value)
0041
0042 def __delete__(self, obj):
0043 self.getter.__delete__(obj)
0044 self.expire(obj)
0045
0046 def expire(self, obj):
0047 try:
0048 delattr(obj, self._attr_name)
0049 except AttributeError:
0050 pass
0051
0052 def __repr__(self):
0053 return simple_repr('cache', self.name, self.getter)
0054
0055class converter(object):
0056
0057 """
0058 Applies a FormEncode validator/converter to a descriptor.
0059 Supports both a class-level ``default_validator``, and custom
0060 validators.
0061
0062 Subclasses (like ``json_converter``) might set
0063 ``default_validator``.
0064 """
0065
0066 default_validator = None
0067
0068 def __init__(self, getter=None, validator=None):
0069 self.getter = getter
0070
0071 self.validator = validator
0072
0073 def __get__(self, obj, type=None):
0074 if obj is None:
0075 return self
0076 value = self.getter.__get__(obj, type)
0077 if self.validator:
0078 value = self.validator.to_python(value)
0079 if self.default_validator:
0080 value = self.default_validator.to_python(value)
0081 return value
0082
0083 def __set__(self, obj, value):
0084 if self.default_validator:
0085 value = self.default_validator.from_python(value)
0086 if self.validator:
0087 value = self.validator.from_python(value)
0088 self.getter.__set__(obj, value)
0089
0090 def __delete__(self, obj):
0091 self.getter.__delete__(obj)
0092
0093 def __repr__(self):
0094 return simple_repr(self.__class__.__name__,
0095 self.getter)
0096
0097 def __getattr__(self, attr):
0098
0099 return getattr(self.getter, attr)
0100
0101class watcher(object):
0102 """
0103 Calls a callback function with (obj, old_value, new_value) everytime
0104 an attribute is set.
0105
0106 You can listen before or after the value is actually set, with
0107 before_watcher and after_watcher. delete_watcher (if given) is
0108 called with (self, old_value) everytime an attribute is deleted,
0109 right before the delete.
0110 """
0111
0112 def __init__(self, getter, before_watcher=None,
0113 after_watcher=None, delete_watcher=None):
0114 self.getter = getter
0115 self.before_watcher = before_watcher
0116 self.after_watcher = after_watcher
0117 self.delete_watcher = delete_watcher
0118
0119 def __get__(self, obj, type=None):
0120 if obj is None:
0121 return self
0122 value = self.getter.__get__(obj, type)
0123 return value
0124
0125 def __set__(self, obj, value):
0126 old_value = self.getter.__get__(obj, None)
0127 if self.before_watcher is not None:
0128 self.before_watcher(obj, old_value, value)
0129 self.getter.__set__(obj, value)
0130 if self.after_watcher is not None:
0131 self.after_watcher(obj, old_value, value)
0132
0133 def __delete__(self, obj):
0134 if self.delete_watcher is not None:
0135 old_value = self.getter.__get__(obj, None)
0136 self.delete_watcher(obj, old_value)
0137 self.getter.__delete__(obj)
0138
0139 def __repr__(self):
0140 kw = {}
0141 if self.before_watcher:
0142 kw['before_watcher'] = self.before_watcher
0143 if self.after_watcher:
0144 kw['after_watcher'] = self.after_watcher
0145 if self.delete_watcher:
0146 kw['delete_watcher'] = self.delete_watcher
0147 return simple_repr(self.__class__.__name__,
0148 self.getter, **kw)
0149
0150
0151class json_converter(converter):
0152 """
0153 Wraps a descriptor and does JSON decoding/encoding.
0154
0155 An underlying string shows up as the JSON it decodes to.
0156 """
0157
0158 default_validator = JSONConverter()
0159
0160class line_converter(converter):
0161 """
0162 Wraps a descriptor, and splits/joins text lines.
0163
0164 An underlying string shows up as a list of strings split by line.
0165 """
0166 default_validator = LineConverter()