xotl.tools.context - Simple execution contexts

A context manager for execution context flags.

xotl.tools.context.context

alias of xotl.tools.context.Context

class xotl.tools.context.Context(*args, **kwargs)[source]

An execution context manager with parameters (or flags).

Use as:

>>> SOME_CONTEXT = object()
>>> from xotl.tools.context import context
>>> with context(SOME_CONTEXT):
...     if context[SOME_CONTEXT]:
...         print('In context SOME_CONTEXT')
In context SOME_CONTEXT

Note the difference creating the context and checking it: for entering a context you should use context(name) for testing whether some piece of code is being executed inside a context you should use context[name]; you may also use the syntax name in context.

When an existing context is re-enter, the former one is reused. Nevertheless, the data stored in each context is local to each level.

For example:

>>> with context('A', b=1) as a1:
...   with context('A', b=2) as a2:
...       print(a1 is a2)
...       print(a2['b'])
...   print(a1['b'])
True
2
1

For data access, a mapping interface is provided for all contexts. If a data slot is deleted at some level, upper level is used to read values. Each new written value is stored in current level without affecting upper levels.

For example:

>>> with context('A', b=1) as a1:
...   with context('A', b=2) as a2:
...       del a2['b']
...       print(a2['b'])
1

It is an error to reuse a context directly like in:

>>> with context('A', b=1) as a1:   
...   with a1:
...       pass
Traceback (most recent call last):
...
RuntimeError: Entering the same context level twice! ...
classmethod from_defaults(ctx, **defaults)[source]

Creates context ctx introducing only new keys given in defaults.

The normal behavior when you enter a new level in the context is to override the values with the new one.

Example:

>>> with context.from_defaults('A', a=1):
...    with context.from_defaults('A', a=2, b=1) as c:
...        assert c['a'] == 1
classmethod from_dicts(ctx, overrides=None, defaults=None)[source]

Creates a context introducing both defaults and overrides.

This combines both the standard constructor and from_defaults().

If the same key appears in both overrides and defaults, ignore the default.

Note

About thread-locals and contexts.

The context uses internally a thread-local instance to keep context stacks in different threads from seeing each other.

If, when this module is imported, greenlet is imported already, greenlet isolation is also warranted (which implies thread isolation).

If you use collaborative multi-tasking based in other framework other than greenlet, you must ensure to monkey patch the threading.local class so that isolation is kept.

In future releases of xotl.tools, we plan to provide a way to inject a “process” identity manager so that other frameworks be easily integrated.

Changed in version 1.7.1: Changed the test about greenlet. Instead of testing for greenlet to be importable, test it is imported already.

Changed in version 1.6.9: Added direct greenlet isolation and removed the need for gevent.local.

New in version 1.6.8: Uses gevent.local if available to isolate greenlets.