Permalink
Browse files

LocalProxy: add __wrapped__ attribute to refer to wrapped function (#924

)
  • Loading branch information...
1 parent 4313cc9 commit 8a84b62b3dd89fe7d720d7948954e20ada690c40 @immerrr immerrr committed with untitaker May 9, 2016
Showing with 32 additions and 1 deletion.
  1. +1 −0 AUTHORS
  2. +2 −0 CHANGES
  3. +24 −0 tests/test_local.py
  4. +5 −1 werkzeug/local.py
View
@@ -29,6 +29,7 @@ Project Leader / Developer:
- Markus Unterwaditzer
- Joe Esposito <joe@joeyespo.com>
- Abhinav Upadhyay <er.abhinav.upadhyay@gmail.com>
+- immerrr <immerrr@gmail.com>
Contributors of code for werkzeug/examples are:
View
@@ -21,6 +21,8 @@ Unreleased.
in the user agent string.
- Recognize SeaMonkey browser name and version correctly
- Recognize Baiduspider, and bingbot user agents
+- If `LocalProxy`'s wrapped object is a function, refer to it with __wrapped__
+ attribute.
Version 0.11.10
---------------
View
@@ -12,6 +12,7 @@
import time
import copy
+from functools import partial
from threading import Thread
from werkzeug import local
@@ -181,3 +182,26 @@ def __deepcopy__(self, memo):
assert copy.deepcopy(p2) == [a]
assert copy.deepcopy(p2)[0] is not a
+
+
+def test_local_proxy_wrapped_attribute():
+ class SomeClassWithWrapped(object):
+ __wrapped__ = 'wrapped'
+
+ def lookup_func():
+ return 42
+
+ partial_lookup_func = partial(lookup_func)
+
+ proxy = local.LocalProxy(lookup_func)
+ assert proxy.__wrapped__ is lookup_func
+
+ partial_proxy = local.LocalProxy(partial_lookup_func)
+ assert partial_proxy.__wrapped__ == partial_lookup_func
+
+ l = local.Local()
+ l.foo = SomeClassWithWrapped()
+ l.bar = 42
+
+ assert l('foo').__wrapped__ == 'wrapped'
+ pytest.raises(AttributeError, lambda: l('bar').__wrapped__)
View
@@ -287,11 +287,15 @@ class LocalProxy(object):
.. versionchanged:: 0.6.1
The class can be instantiated with a callable as well now.
"""
- __slots__ = ('__local', '__dict__', '__name__')
+ __slots__ = ('__local', '__dict__', '__name__', '__wrapped__')
def __init__(self, local, name=None):
object.__setattr__(self, '_LocalProxy__local', local)
object.__setattr__(self, '__name__', name)
+ if callable(local) and not hasattr(local, '__release_local__'):
+ # "local" is a callable that is not an instance of Local or
+ # LocalManager: mark it as a wrapped function.
+ object.__setattr__(self, '__wrapped__', local)
def _get_current_object(self):
"""Return the current object. This is useful if you want the real

0 comments on commit 8a84b62

Please sign in to comment.