From: Jason Kirtland Date: Fri, 17 Oct 2008 20:04:11 +0000 (+0000) Subject: Moved r5164's @lazy_property to @memoized_property, updated existing @memoize consumers. X-Git-Tag: rel_0_5rc3~73 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=654794cdcf89eb7842ddf06bd9316bd860bca9e7;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Moved r5164's @lazy_property to @memoized_property, updated existing @memoize consumers. --- diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index dd30bdda7a..bd96b9e695 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -281,15 +281,13 @@ class Mapper(object): return from_obj - @property - @util.memoize + @util.memoized_property def _with_polymorphic_mappers(self): if not self.with_polymorphic: return [self] return self.__mappers_from_spec(*self.with_polymorphic) - @property - @util.memoize + @util.memoized_property def _with_polymorphic_selectable(self): if not self.with_polymorphic: return self.mapped_table @@ -560,8 +558,7 @@ class Mapper(object): self.primary_key = primary_key self.__log("Identified primary key columns: " + str(primary_key)) - @property - @util.memoize + @util.memoized_property def _get_clause(self): """create a "get clause" based on the primary key. this is used by query.get() and many-to-one lazyloads to load this item @@ -571,8 +568,7 @@ class Mapper(object): params = [(primary_key, sql.bindparam(None, type_=primary_key.type)) for primary_key in self.primary_key] return sql.and_(*[k==v for (k, v) in params]), dict(params) - @property - @util.memoize + @util.memoized_property def _equivalent_columns(self): """Create a map of all *equivalent* columns, based on the determination of column pairs that are equated to diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 45360d84a2..d2f5dae0c8 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -83,7 +83,7 @@ class ColumnProperty(StrategizedProperty): return value class ColumnComparator(PropComparator): - @util.memoize + @util.memoized_instancemethod def __clause_element__(self): return self.prop.columns[0]._annotate({"parententity": self.mapper}) diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py index 52bf1578e4..103af45131 100644 --- a/lib/sqlalchemy/orm/unitofwork.py +++ b/lib/sqlalchemy/orm/unitofwork.py @@ -342,7 +342,7 @@ class UOWTask(object): self.dependencies = set() self.cyclical_dependencies = set() - @util.lazy_property + @util.memoized_property def inheriting_mappers(self): return list(self.mapper.polymorphic_iterator()) diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py index 770b48796c..925c593498 100644 --- a/lib/sqlalchemy/util.py +++ b/lib/sqlalchemy/util.py @@ -395,19 +395,6 @@ def iterate_attributes(cls): yield (key, c.__dict__[key]) break -class lazy_property(object): - """A read-only @property that is only evaluated once.""" - def __init__(self, fget, doc=None): - self.fget = fget - self.__doc__ = doc or fget.__doc__ - self.__name__ = fget.__name__ - - def __get__(self, obj, cls): - if obj is None: - return None - obj.__dict__[self.__name__] = result = self.fget(obj) - return result - # from paste.deploy.converters def asbool(obj): if isinstance(obj, (str, unicode)): @@ -1283,23 +1270,52 @@ def function_named(fn, name): fn.func_defaults, fn.func_closure) return fn -@decorator -def memoize(fn, self): - """apply caching to the return value of a function.""" +class memoized_property(object): + """A read-only @property that is only evaluated once.""" + def __init__(self, fget, doc=None): + self.fget = fget + self.__doc__ = doc or fget.__doc__ + self.__name__ = fget.__name__ - name = '_cached_' + fn.__name__ + def __get__(self, obj, cls): + if obj is None: + return None + obj.__dict__[self.__name__] = result = self.fget(obj) + return result + + +class memoized_instancemethod(object): + """Decorate a method memoize its return value. + + Best applied to no-arg methods: memoization is not sensitive to + argument values, and will always return the same value even when + called with different arguments. + + """ + def __init__(self, fget, doc=None): + self.fget = fget + self.__doc__ = doc or fget.__doc__ + self.__name__ = fget.__name__ + + def __get__(self, obj, cls): + if obj is None: + return None + def oneshot(*args, **kw): + result = self.fget(obj, *args, **kw) + memo = lambda *a, **kw: result + memo.__name__ = self.__name__ + memo.__doc__ = self.__doc__ + obj.__dict__[self.__name__] = memo + return result + oneshot.__name__ = self.__name__ + oneshot.__doc__ = self.__doc__ + return oneshot - try: - return getattr(self, name) - except AttributeError: - value = fn(self) - setattr(self, name, value) - return value def reset_memoized(instance, name): try: - delattr(instance, '_cached_' + name) - except AttributeError: + del instance.__dict__[name] + except KeyError: pass class WeakIdentityMapping(weakref.WeakKeyDictionary):