Dynamic Python Diagnostics
Beacon reports dynamic Python boundaries when runtime behavior can change names, types, imports, or class layout in ways static analysis cannot model precisely.
DYN001 – DynamicBoundary
Emitted when code crosses a dynamic boundary that may hide type-relevant behavior. Severity is mode-aware:
- strict: error
- balanced: warning
- relaxed: hint
Common triggers include:
setattr/delattrmonkey-patching;- runtime
__class__or__bases__mutation; - custom metaclasses and
type(name, bases, namespace)class creation; - non-literal
getattr(obj, name)reflection; __import__orimportlib.import_moduledynamic imports;- custom import hooks and
sys.pathmutation; eval,exec, orcompilegenerated code;- decorators that may replace functions or classes;
- runtime
__all__mutation.
import sys
def load(name: str):
return __import__(name) # DYN001
def patch(obj: object) -> None:
setattr(obj, "field", 1) # DYN001
sys.meta_path.append(object()) # DYN001
Supported patterns such as literal getattr(obj, "name"), hasattr, and an
annotated __getattr__ method act as explicit fallback boundaries and do not
produce this diagnostic by themselves.
Fix by replacing dynamic behavior with ordinary imports, declared attributes,
stubs, protocols, or typed wrapper functions where possible. If the dynamic
boundary is intentional, isolate it and annotate the result as Any.