# Path: soap/common/cache.py
# class Flyweight(object):
# 
#     _cache = weakref.WeakValueDictionary()
# 
#     def __new__(cls, *args, **kwargs):
#         if not args and not kwargs:
#             return object.__new__(cls)
#         key = pickle.dumps((cls, args, list(kwargs.items())))
#         v = cls._cache.get(key, None)
#         if v is not None:
#             return v
#         v = object.__new__(cls)
#         cls._cache[key] = v
#         return v


import functools
from soap.common.cache import Flyweight
        @functools.wraps(decd_func)
        def wrapper(self, other):
            t = base_func(self, other)
            if t is not None:
                return t
            return decd_func(self, other)

        return wrapper

    cls.__str__ = decorate_self(Lattice.__str__, cls.__str__)
    cls.__repr__ = decorate_self(Lattice.__repr__, cls.__repr__)
    cls.__hash__ = decorate_self(Lattice.__hash__, cls.__hash__)
    cls.is_top = decorate_self(Lattice.is_top, cls.is_top)
    cls.is_bottom = decorate_self(Lattice.is_bottom, cls.is_bottom)
    cls.join = decorate_self_other(Lattice.join, cls.join)
    cls.meet = decorate_self_other(Lattice.meet, cls.meet)
    cls.le = decorate_self_other(Lattice.le, cls.le)
    cls._decorated.add(cls)
    return cls


def _compare(func):
    def wrapped_func(self, other):
        try:
            return func(self, other)
        except AttributeError:
            return False
    return wrapped_func



# Path: soap/common/cache.py
# class Flyweight(object):
# 
#     _cache = weakref.WeakValueDictionary()
# 
#     def __new__(cls, *args, **kwargs):
#         if not args and not kwargs:
#             return object.__new__(cls)
#         key = pickle.dumps((cls, args, list(kwargs.items())))
#         v = cls._cache.get(key, None)
#         if v is not None:
#             return v
#         v = object.__new__(cls)
#         cls._cache[key] = v
#         return v


# Path: soap/lattice/base.py
import functools
from soap.common.cache import Flyweight

        @functools.wraps(decd_func)
        def wrapper(self, other):
            t = base_func(self, other)
            if t is not None:
                return t
            return decd_func(self, other)

        return wrapper

    cls.__str__ = decorate_self(Lattice.__str__, cls.__str__)
    cls.__repr__ = decorate_self(Lattice.__repr__, cls.__repr__)
    cls.__hash__ = decorate_self(Lattice.__hash__, cls.__hash__)
    cls.is_top = decorate_self(Lattice.is_top, cls.is_top)
    cls.is_bottom = decorate_self(Lattice.is_bottom, cls.is_bottom)
    cls.join = decorate_self_other(Lattice.join, cls.join)
    cls.meet = decorate_self_other(Lattice.meet, cls.meet)
    cls.le = decorate_self_other(Lattice.le, cls.le)
    cls._decorated.add(cls)
    return cls


def _compare(func):
    def wrapped_func(self, other):
        try:
            return func(self, other)
        except AttributeError:
            return False
    return wrapped_func



class Lattice(Flyweight):