Skip to content

Commit

Permalink
LocalProxy: add __wrapped__ attribute to refer to wrapped function (#924
Browse files Browse the repository at this point in the history
)
  • Loading branch information
immerrr authored and untitaker committed May 9, 2016
1 parent 4313cc9 commit 8a84b62
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 1 deletion.
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -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:

Expand Down
2 changes: 2 additions & 0 deletions CHANGES
Expand Up @@ -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
---------------
Expand Down
24 changes: 24 additions & 0 deletions tests/test_local.py
Expand Up @@ -12,6 +12,7 @@

import time
import copy
from functools import partial
from threading import Thread

from werkzeug import local
Expand Down Expand Up @@ -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__)
6 changes: 5 additions & 1 deletion werkzeug/local.py
Expand Up @@ -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
Expand Down

0 comments on commit 8a84b62

Please sign in to comment.