pf.tracer

Members

class procfunc.tracer.TraceLevel[source]

Bases: IntEnum

Higher = coarser. Lower = finer.

The resulting graph will contain nodes which are this level

GRAMMAR = 100
RANDOM_CONTROL = 60
RANDOM_PARAMS = 50
GENERATORS = 40
NODEGROUPS = 30
PRIMITIVES = 20

Supported special methods: __abs__, __add__, __and__, __bool__, __ceil__, __contains__, __divmod__, __float__, __floor__, __floordiv__, __getitem__, __getnewargs__, __index__, __int__, __invert__, __iter__, __len__, __lshift__, __mod__, __mul__, __neg__, __or__, __pos__, __pow__, __radd__, __rand__, __rdivmod__, __rfloordiv__, __rlshift__, __rmod__, __rmul__, __ror__, __round__, __rpow__, __rrshift__, __rshift__, __rsub__, __rtruediv__, __rxor__, __sub__, __truediv__, __trunc__, __xor__

procfunc.tracer.grammar(func=None, *, allow_exec=False, custom_trace_wrapper_create=None, mutates=None, normalize=True)
Parameters:
Return type:

Callable

procfunc.tracer.random_control(func=None, *, allow_exec=False, custom_trace_wrapper_create=None, mutates=None, normalize=True)
Parameters:
Return type:

Callable

procfunc.tracer.random_param(func=None, *, allow_exec=False, custom_trace_wrapper_create=None, mutates=None, normalize=True)
Parameters:
Return type:

Callable

procfunc.tracer.generator(func=None, *, allow_exec=False, custom_trace_wrapper_create=None, mutates=None, normalize=True)
Parameters:
Return type:

Callable

procfunc.tracer.primitive(func=None, *, allow_exec=False, custom_trace_wrapper_create=None, mutates=None, normalize=True)
Parameters:
Return type:

Callable

class procfunc.tracer.RngProxy[source]

Bases: Proxy

We will do specialcase handling to trace rng nodes through the graph

This allows us to know what the results of choice() and other random control flow will be, BUT only if the user has kept the rng non-dirty, i.e. the rng used for choice descends from the root via only spawn() calls

This is essential so that the result of choice() during tracing is the same as the result of choice() during generation

__init__(node, rng, dirty=False)[source]
Parameters:
rng: Generator
dirty: bool = False
spawn(n_children)[source]

Returns a mock node which can only be unpacked into its constitutent mock rngs

Parameters:

n_children (int)

Return type:

RngSpawnResultProxy

Supported special methods: __abs__, __add__, __and__, __bool__, __call__, __floordiv__, __getattr__, __getitem__, __invert__, __iter__, __len__, __lshift__, __mod__, __mul__, __neg__, __or__, __pos__, __pow__, __radd__, __rand___, __rfloordiv__, __rlshift__, __rmod__, __rmul__, __ror___, __rpow__, __rrshift__, __rshift__, __rsub__, __rtruediv__, __rxor__, __sub__, __truediv__, __xor__

class procfunc.tracer.RngSpawnResultProxy[source]

Bases: Proxy

RngSpawnResultProxy(node: procfunc.compute_graph.node.Node, from_rng_proxy: ‘RngProxy’, child_rngs: list[numpy.random._generator.Generator], dirty: bool = False)

__init__(node, from_rng_proxy, child_rngs, dirty=False)[source]
Parameters:
from_rng_proxy: RngProxy
child_rngs: list[Generator]
dirty: bool = False

Supported special methods: __abs__, __add__, __and__, __bool__, __call__, __floordiv__, __getattr__, __getitem__, __invert__, __iter__, __len__, __lshift__, __mod__, __mul__, __neg__, __or__, __pos__, __pow__, __radd__, __rand___, __rfloordiv__, __rlshift__, __rmod__, __rmul__, __ror___, __rpow__, __rrshift__, __rshift__, __rsub__, __rtruediv__, __rxor__, __sub__, __truediv__, __xor__

class procfunc.tracer.Patcher[source]

Bases: object

A ‘patch’ is an invasive modification of another module (e.g numpy, math) which makes their functions behave differently for tracing

This class creates patches and records them so that we can undo them later

__init__(trace_level, autopatch_wrap_modules=None, autopatch_remove_modules=None, patch_functions=None, search_scopes=None)[source]
Parameters:
patched: list[Patch]
visited_frames: set[int]
apply_preexecute_patches(func, trace_level=None)[source]
Parameters:
create_wrapper(func)[source]
Parameters:

func (Callable)

search_autowrap_targets(frame)[source]
Parameters:

frame (dict)

patch(patch)[source]
Parameters:

patch (Patch)

unpatch_all()[source]

Supported special methods: __enter__, __exit__

class procfunc.tracer.PatchFunctionTarget[source]

Bases: object

PatchFunctionTarget(frame: dict, name: str, trace_level: procfunc.tracer.patch.TraceLevel, normalize: bool = True, allow_exec: bool = False, custom_trace_wrapper_create: Optional[Callable[[ForwardRef(‘PatchFunctionTarget’), ForwardRef(‘Patcher’)], Callable]] = None, source_name: str | None = None, mutates: list[str] | None = None)

frame: dict
name: str
trace_level: TraceLevel
normalize: bool = True
allow_exec: bool = False
custom_trace_wrapper_create: Callable[[PatchFunctionTarget, Patcher], Callable] | None = None
source_name: str | None = None
mutates: list[str] | None = None
__init__(frame, name, trace_level, normalize=True, allow_exec=False, custom_trace_wrapper_create=None, source_name=None, mutates=None)
Parameters:
Return type:

None

procfunc.tracer.trace(func, trace_level=TraceLevel.GENERATORS, name=None, **inputs)[source]

Turn a python function into a graph datastructure.

Using this datastructure is (usually) equivelent to executing the function.

Parameters:
  • func (Callable) – The function to trace

  • trace_level (TraceLevel) – Granularity of the graph. Functions at this level become leaves; finer functions are traced through. choice() peeks through all options when trace_level >= RANDOM_CONTROL, or resolves to the chosen branch when finer.

  • name (str | None)

  • inputs (Any)

procfunc.tracer.add_banned_module(module)[source]
Parameters:

module (ModuleType)

procfunc.tracer.add_wrap_target(target)[source]
Parameters:

target (PatchFunctionTarget)

procfunc.tracer.autowrap_module(module, allow_exec=False, trace_level=TraceLevel.PRIMITIVES)[source]
Parameters: