ContextualValue#

class treescope.context.ContextualValue[source]#

Bases: Generic[T]

A global value which can be modified in a scoped context.

Mutable global values can be difficult to reason about, but can also be very convenient for reducing boilerplate and focusing on the important parts if they are used carefully. Moreover, it’s common to only want to change a global value within a particular delimited scope, without affecting anything beyond that scope.

This class manages a global value that can be read anywhere, and modified either globally or within a delimited scope. Local values always take precedence over global values.

When used within a function, it is usually recommended to use scoped updates. If you have many values to set, or you want to set them conditionally, consider using a contextlib.ExitStack, e.g.

with contextlib.ExitStack() as stack:
  stack.enter_context(contextual_one.set_scoped(True))
  if foo:
    stack.enter_context(contextual_two.set_scoped(some_value))
  # logic that uses those values
# all contexts are exited here

or just

stack = contextlib.ExitStack()
stack.enter_context(contextual_one.set_scoped(True))
if foo:
  stack.enter_context(contextual_two.set_scoped(some_value))
# ... do something ...
# ... then eventually:
stack.close()
Variables:
  • __module__ (str | None) – The module where this contextual value is defined.

  • __qualname__ (str | None) – The fully-qualified name of the contextual value within its module.

  • _raw_global_value (T) – The current value at the global level. Should not be used directly.

  • _raw_scoped_value (T | _NoScopedValue) – The current value at the scoped level. Should not be used directly.

Methods

__init__(initial_value[, module, qualname])

Creates a contextual value.

get()

Retrieves the current value.

set_globally(new_value)

Sets the value at the global level.

set_scoped(new_value)

Returns a context manager in which the value will be modified.

__init__(initial_value: T, module: str | None = None, qualname: str | None = None)[source]#

Creates a contextual value.

Parameters:
  • initial_value – A value to use outside of set_scoped contexts.

  • module – The module where this contextual value is defined. Usually this will be __name__ (for whichever model it was defined in).

  • qualname – The fully-qualified name of the contextual value within its module.

get() T[source]#

Retrieves the current value.

set_globally(new_value: T) None[source]#

Sets the value at the global level.

Updates at the global level will be overridden by any scoped updates.

Parameters:

new_value – The new value to use.

set_scoped(new_value: T)[source]#

Returns a context manager in which the value will be modified.

This allows scoped modifications to the value, using something like

contextual = ContextualValue(10)

with contextual.set_scoped(3):
  v1 = contextual.get()  # v1 is 3

v2 = contextual.get()  # v2 is 10

If you want to conditionally set the value, consider using contextlib.ExitStack:

with contextlib.ExitStack() as exit_stack:
  if condition:
    exit_stack.enter_context(contextual.set_scoped(3))

  # use contextual.get() here
Parameters:

new_value – The new value to use in this context.

Returns:

A context manager in which new_value is set.