summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBert JW Regeer <xistence@0x58.com>2020-01-05 20:02:26 -0800
committerGitHub <noreply@github.com>2020-01-05 20:02:26 -0800
commit5702c3c3a4357a6071c9ba624a89655209548336 (patch)
treebc8d03a5c7927ea3ae2a868fd5af8e1a2cff7c6b /src
parent148cf5138638ce6b1b92b4e13fe1444df9451e34 (diff)
parent5cad7ad7ce47f1fe151b40ae9398fb5cbbfd3806 (diff)
downloadpyramid-5702c3c3a4357a6071c9ba624a89655209548336.tar.gz
pyramid-5702c3c3a4357a6071c9ba624a89655209548336.tar.bz2
pyramid-5702c3c3a4357a6071c9ba624a89655209548336.zip
Merge pull request #3559 from mmerickel/settable-properties
allow overriding synthesized properties
Diffstat (limited to 'src')
-rw-r--r--src/pyramid/util.py57
1 files changed, 40 insertions, 17 deletions
diff --git a/src/pyramid/util.py b/src/pyramid/util.py
index e552b37de..504516631 100644
--- a/src/pyramid/util.py
+++ b/src/pyramid/util.py
@@ -73,6 +73,26 @@ def as_sorted_tuple(val):
return val
+class SettableProperty(object):
+ def __init__(self, wrapped):
+ self.wrapped = wrapped
+ 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.wrapped.__name__, _marker)
+ if value is _marker:
+ value = self.wrapped(obj)
+ return value
+
+ def __set__(self, obj, value):
+ obj.__dict__[self.wrapped.__name__] = value
+
+ def __delete__(self, obj):
+ del obj.__dict__[self.wrapped.__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
@@ -94,26 +114,29 @@ 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__
+ name = get_callable_name(name)
+ is_data_descriptor = hasattr(callable, '__set__')
+ if reify and is_data_descriptor:
+ raise ValueError('cannot reify a data descriptor')
+ if is_data_descriptor:
fn = callable
- if reify:
- import pyramid.decorator # avoid circular import
+ 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(fn)
- elif not is_property:
- fn = property(fn)
+ fn = pyramid.decorator.reify(wrapped)
+ else:
+ fn = SettableProperty(wrapped)
return name, fn