/usr/lib/python3/dist-packages/twisted/python/context.py is in python3-twisted-experimental 13.2.0-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | # -*- test-case-name: twisted.test.test_context -*-
# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.
"""
Dynamic pseudo-scoping for Python.
Call functions with context.call({key: value}, func); func and
functions that it calls will be able to use 'context.get(key)' to
retrieve 'value'.
This is thread-safe.
"""
from __future__ import division, absolute_import
from threading import local
defaultContextDict = {}
setDefault = defaultContextDict.__setitem__
class ContextTracker:
"""
A L{ContextTracker} provides a way to pass arbitrary key/value data up and
down a call stack without passing them as parameters to the functions on
that call stack.
This can be useful when functions on the top and bottom of the call stack
need to cooperate but the functions in between them do not allow passing the
necessary state. For example::
from twisted.python.context import call, get
def handleRequest(request):
call({'request-id': request.id}, renderRequest, request.url)
def renderRequest(url):
renderHeader(url)
renderBody(url)
def renderHeader(url):
return "the header"
def renderBody(url):
return "the body (request id=%r)" % (get("request-id"),)
This should be used sparingly, since the lack of a clear connection between
the two halves can result in code which is difficult to understand and
maintain.
@ivar contexts: A C{list} of C{dict}s tracking the context state. Each new
L{ContextTracker.callWithContext} pushes a new C{dict} onto this stack
for the duration of the call, making the data available to the function
called and restoring the previous data once it is complete..
"""
def __init__(self):
self.contexts = [defaultContextDict]
def callWithContext(self, newContext, func, *args, **kw):
"""
Call C{func(*args, **kw)} such that the contents of C{newContext} will
be available for it to retrieve using L{getContext}.
@param newContext: A C{dict} of data to push onto the context for the
duration of the call to C{func}.
@param func: A callable which will be called.
@param *args: Any additional positional arguments to pass to C{func}.
@param **kw: Any additional keyword arguments to pass to C{func}.
@return: Whatever is returned by C{func}
@raise: Whatever is raised by C{func}.
"""
self.contexts.append(newContext)
try:
return func(*args,**kw)
finally:
self.contexts.pop()
def getContext(self, key, default=None):
"""
Retrieve the value for a key from the context.
@param key: The key to look up in the context.
@param default: The value to return if C{key} is not found in the
context.
@return: The value most recently remembered in the context for C{key}.
"""
for ctx in reversed(self.contexts):
try:
return ctx[key]
except KeyError:
pass
return default
class ThreadedContextTracker(object):
def __init__(self):
self.storage = local()
def currentContext(self):
try:
return self.storage.ct
except AttributeError:
ct = self.storage.ct = ContextTracker()
return ct
def callWithContext(self, ctx, func, *args, **kw):
return self.currentContext().callWithContext(ctx, func, *args, **kw)
def getContext(self, key, default=None):
return self.currentContext().getContext(key, default)
def installContextTracker(ctr):
global theContextTracker
global call
global get
theContextTracker = ctr
call = theContextTracker.callWithContext
get = theContextTracker.getContext
installContextTracker(ThreadedContextTracker())
|