properties.pyx 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. from cython import Py_ssize_t
  2. from cpython.dict cimport (
  3. PyDict_Contains,
  4. PyDict_GetItem,
  5. PyDict_SetItem,
  6. )
  7. cdef class CachedProperty:
  8. cdef readonly:
  9. object func, name, __doc__
  10. def __init__(self, func):
  11. self.func = func
  12. self.name = func.__name__
  13. self.__doc__ = getattr(func, '__doc__', None)
  14. def __get__(self, obj, typ):
  15. if obj is None:
  16. # accessed on the class, not the instance
  17. return self
  18. # Get the cache or set a default one if needed
  19. cache = getattr(obj, '_cache', None)
  20. if cache is None:
  21. try:
  22. cache = obj._cache = {}
  23. except (AttributeError):
  24. return self
  25. if PyDict_Contains(cache, self.name):
  26. # not necessary to Py_INCREF
  27. val = <object>PyDict_GetItem(cache, self.name)
  28. else:
  29. val = self.func(obj)
  30. PyDict_SetItem(cache, self.name, val)
  31. return val
  32. def __set__(self, obj, value):
  33. raise AttributeError("Can't set attribute")
  34. cache_readonly = CachedProperty
  35. cdef class AxisProperty:
  36. cdef readonly:
  37. Py_ssize_t axis
  38. object __doc__
  39. def __init__(self, axis=0, doc=""):
  40. self.axis = axis
  41. self.__doc__ = doc
  42. def __get__(self, obj, type):
  43. cdef:
  44. list axes
  45. if obj is None:
  46. # Only instances have _mgr, not classes
  47. return self
  48. else:
  49. axes = obj._mgr.axes
  50. return axes[self.axis]
  51. def __set__(self, obj, value):
  52. obj._set_axis(self.axis, value)