From c5dd748a3bc06b6e7e17797863bb363a2f377a5e Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 5 Jan 2020 18:47:52 -0600 Subject: allow overriding synthesized properties --- src/pyramid/util.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/pyramid/util.py b/src/pyramid/util.py index e552b37de..ca644dcce 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -73,6 +73,27 @@ def as_sorted_tuple(val): return val +class SettableProperty(object): + def __init__(self, wrapped, name): + self.wrapped = wrapped + self.name = name + functools.update_wrapper(self, wrapped) + + def __get__(self, obj, type=None): + if obj is None: # pragma: no cover + return self + value = obj.__dict__.get(self.name, _marker) + if value is _marker: + value = self.wrapped(obj) + return value + + def __set__(self, obj, value): + obj.__dict__[self.name] = value + + def __delete__(self, obj): + del obj.__dict__[self.name] + + class InstancePropertyHelper(object): """A helper object for assigning properties and descriptors to instances. It is not normally possible to do this because descriptors must be @@ -113,7 +134,7 @@ class InstancePropertyHelper(object): fn = pyramid.decorator.reify(fn) elif not is_property: - fn = property(fn) + fn = SettableProperty(fn, name) return name, fn -- cgit v1.2.3 From db8ab619a09b90c633d78ce5487703bf72ea4111 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 5 Jan 2020 19:24:19 -0600 Subject: support using descriptors other than property --- src/pyramid/util.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/pyramid/util.py b/src/pyramid/util.py index ca644dcce..9024fe816 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -115,26 +115,26 @@ class InstancePropertyHelper(object): (name, property) pair. """ - is_property = isinstance(callable, property) - if is_property: - fn = callable - if name is None: - raise ValueError('must specify "name" for a property') - if reify: - raise ValueError('cannot reify a property') - elif name is not None: - fn = lambda this: callable(this) - fn.__name__ = get_callable_name(name) - fn.__doc__ = callable.__doc__ - else: + if name is None: + if not hasattr(callable, '__name__'): + raise ValueError( + 'missing __name__, must specify "name" for property' + ) name = callable.__name__ - fn = callable + name = get_callable_name(name) + is_data_descriptor = hasattr(callable, '__set__') + if reify and is_data_descriptor: + raise ValueError('cannot reify a data descriptor') + fn = callable if reify: import pyramid.decorator # avoid circular import + fn = lambda this: callable(this) + fn.__name__ = name + fn.__doc__ = callable.__doc__ fn = pyramid.decorator.reify(fn) - elif not is_property: - fn = SettableProperty(fn, name) + elif not is_data_descriptor: + fn = SettableProperty(callable, name) return name, fn -- cgit v1.2.3 From 5cad7ad7ce47f1fe151b40ae9398fb5cbbfd3806 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 5 Jan 2020 21:24:35 -0600 Subject: handle settable property same as reify --- src/pyramid/util.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/pyramid/util.py b/src/pyramid/util.py index 9024fe816..504516631 100644 --- a/src/pyramid/util.py +++ b/src/pyramid/util.py @@ -74,24 +74,23 @@ def as_sorted_tuple(val): class SettableProperty(object): - def __init__(self, wrapped, name): + def __init__(self, wrapped): self.wrapped = wrapped - self.name = name functools.update_wrapper(self, wrapped) def __get__(self, obj, type=None): if obj is None: # pragma: no cover return self - value = obj.__dict__.get(self.name, _marker) + value = obj.__dict__.get(self.wrapped.__name__, _marker) if value is _marker: value = self.wrapped(obj) return value def __set__(self, obj, value): - obj.__dict__[self.name] = value + obj.__dict__[self.wrapped.__name__] = value def __delete__(self, obj): - del obj.__dict__[self.name] + del obj.__dict__[self.wrapped.__name__] class InstancePropertyHelper(object): @@ -125,16 +124,19 @@ class InstancePropertyHelper(object): is_data_descriptor = hasattr(callable, '__set__') if reify and is_data_descriptor: raise ValueError('cannot reify a data descriptor') - fn = callable - if reify: - import pyramid.decorator # avoid circular import - - fn = lambda this: callable(this) - fn.__name__ = name - fn.__doc__ = callable.__doc__ - fn = pyramid.decorator.reify(fn) - elif not is_data_descriptor: - fn = SettableProperty(callable, name) + if is_data_descriptor: + fn = callable + else: + wrapped = lambda this: callable(this) + wrapped.__name__ = name + wrapped.__doc__ = callable.__doc__ + + if reify: + import pyramid.decorator # avoid circular import + + fn = pyramid.decorator.reify(wrapped) + else: + fn = SettableProperty(wrapped) return name, fn -- cgit v1.2.3