"""Helpers for class definitions."""

__all__ = [
    'LazyAttrs',
    'NondataProperty',
    'memorize',
    'nondata_property',
]

import functools

from garage import asserts


class LazyAttrs:
    """Compute (and store) attributes lazily."""

    def __init__(self, compute_attrs):
        self.__compute_attrs = compute_attrs
        self.__attrs = {}

    def __getattr__(self, name):
        if name not in self.__attrs:
            self.__compute_attrs(name, self.__attrs)
        return self.__attrs[name]


class NondataProperty:
    """A non-data descriptor version of property.

       This is "non-data" means that instances may override it.
    """

    def __init__(self, fget=None, doc=None):
        self.fget = fget
        if doc is None and fget is not None:
            doc = fget.__doc__
        self.__doc__ = doc

    def __get__(self, instance, _=None):
        if instance is None:
            return self
        if self.fget is None:
            raise AttributeError('unreadable attribute')
        return self.fget(instance)

    def getter(self, fget):
        return type(self)(fget, self.__doc__)


def nondata_property(fget=None, doc=None):
    return NondataProperty(fget, doc)


def memorize(method):
    """Wrap a method in NondataProperty and then override (i.e.,
       memorize) it with the result.

       Note: method's name _must_ be the same as the property name.
    """
    asserts.precond(not isinstance(method, property))
    asserts.precond(method.__name__ != '<lambda>')
    @functools.wraps(method)
    def wrapper(self):
        value = method(self)
        # Override the wrapper before return.
        self.__dict__[method.__name__] = value
        return value
    return nondata_property(wrapper)

@@ -327,34 +327,8 @@
 ttrs
-%0A        self.__attrs = %7B%7D
 %0A%0A  
@@ -362,49 +362,8 @@
 e):%0A
-        if name not in self.__attrs:%0A    
     
@@ -400,21 +400,22 @@
  self.__
-attrs
+dict__
 )%0A      
@@ -430,21 +430,22 @@
  self.__
-attrs
+dict__
 %5Bname%5D%0A%0A

Use __dict__ in LazyAttrs