Trace Filtering

By default, frontrun only traces user code — files outside the Python stdlib, site-packages, and frontrun’s own internals. This keeps the per-opcode overhead low and avoids producing thousands of spurious scheduling points inside library code (e.g. SQLAlchemy’s internal exec/compile calls, dataclass __init__ methods, etc.).

Sometimes, however, the code under test lives inside an installed package. This is common with Django apps, plugin-based architectures, and any project where business logic is distributed across separately installable packages. The trace_packages parameter lets you widen the filter to include specific installed packages.

trace_packages parameter

All exploration entry points accept an optional trace_packages argument — a list of package-name patterns using fnmatch syntax (* matches any string, ? matches one character).

from frontrun.dpor import explore_dpor

result = explore_dpor(
    setup=make_state,
    threads=[thread_a, thread_b],
    invariant=check_invariant,
    trace_packages=["mylib.*", "django_filters.*"],
)

Patterns are matched against the dotted module name derived from the file’s path inside site-packages. For example, a file at site-packages/django_filters/views.py has module name django_filters.views.

Note

In fnmatch syntax, * matches any characters including dots. This means django_* matches both django_filters (top-level) and django_filters.views (submodule). If you need to match only the top-level package, there is no need — matching submodules is almost always the desired behaviour.

Pattern examples

Pattern

Matches

django_*

django_filters, django_filters.views, django_rest_framework, etc. (top-level + all submodules)

django_filters.*

django_filters.views, django_filters.filters, etc. (submodules only, not django_filters itself)

myapp.*

myapp.models, myapp.views, myapp.utils.helpers, etc.

*

Everything in site-packages (not recommended — very slow)

These entry points accept trace_packages:

Django integration

django_dpor() defaults trace_packages to DJANGO_TRACE_PACKAGES:

DJANGO_TRACE_PACKAGES = ["django_*", "django.contrib.sites.*"]

This means Django third-party apps (django_filters, django_rest_framework, etc.) and django.contrib.sites submodules are traced automatically when using django_dpor.

To add more packages, pass your own list:

from frontrun.contrib.django import django_dpor

result = django_dpor(
    setup=make_state,
    threads=[thread_a, thread_b],
    invariant=check_invariant,
    trace_packages=["django_*", "django.contrib.sites.*", "myapp.*"],
)

To disable extra tracing entirely (trace only user code), pass an empty list:

result = django_dpor(
    setup=make_state,
    threads=[thread_a, thread_b],
    invariant=check_invariant,
    trace_packages=[],
)

Advanced: TraceFilter class

Under the hood, trace_packages creates a TraceFilter instance and installs it as the active filter for the duration of the exploration. You can also create and inspect TraceFilter objects directly:

from frontrun._tracing import TraceFilter

filt = TraceFilter(trace_packages=["django_*", "mylib.*"])

# Test whether a specific file would be traced:
filt.should_trace_file("/path/to/site-packages/django_filters/views.py")
# -> True

filt.should_trace_file("/path/to/site-packages/requests/api.py")
# -> False

Files that are always excluded regardless of trace_packages:

  • threading.py (threading internals)

  • <frozen ...> modules (frozen stdlib)

  • Frontrun’s own package directory

frontrun.contrib.django.DJANGO_TRACE_PACKAGES = ['django_*', 'django.contrib.sites.*']

Built-in mutable sequence.

If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

class frontrun._tracing.TraceFilter(trace_packages=None)[source]

Configurable filter deciding which files should be traced.

The default filter (trace_packages=None) traces only user code: files outside stdlib, site-packages, and frontrun internals.

When trace_packages is provided, files in site-packages whose module names match any of the given patterns are also traced. Patterns use fnmatch.fnmatch() syntax (e.g. "django_*", "mylib.*"). Note that * in fnmatch matches any characters including dots, so "django_*" matches both django_filters and django_filters.views.

Example:

# Trace user code + any django_* package + myapp.utils
filt = TraceFilter(trace_packages=["django_*", "myapp.*"])
filt.should_trace_file("/path/to/site-packages/django_filters/views.py")
# -> True
Parameters:

trace_packages (Sequence[str] | None)

should_trace_file(filename)[source]

Check whether filename should be traced.

Parameters:

filename (str)

Return type:

bool