Description:
The current CLI implementation relies on injecting the _ferret_profiler instance directly into the builtins module to make it available to the instrumented AST. This is a "magical" and fragile approach that poses significant stability risks:
- Namespace Pollution: It modifies the global python environment, which can conflict with user code or other libraries that might use a similar variable name.
- Shadowing Risks: If a user script accidentally defines a variable named
_ferret_profiler, the instrumentation will crash or behave unpredictably.
- Refactoring Difficulty: It creates a hidden, implicit dependency that makes the codebase harder to test and maintain.
Proposed Solution:
Replace the builtins injection with a robust Singleton Accessor Pattern. The FerretInstrumentor should inject explicit import statements into the user's AST that retrieve the active profiler from a safe, module-level accessor.
Tasks:
Acceptance Criteria:
- Running
ferret run script.py works without builtins._ferret_profiler being present in the locals() or globals() of the user script.
- User scripts that define their own
_ferret_profiler variable do not cause the profiler to crash.
Description:
The current CLI implementation relies on injecting the
_ferret_profilerinstance directly into thebuiltinsmodule to make it available to the instrumented AST. This is a "magical" and fragile approach that poses significant stability risks:_ferret_profiler, the instrumentation will crash or behave unpredictably.Proposed Solution:
Replace the builtins injection with a robust Singleton Accessor Pattern. The
FerretInstrumentorshould inject explicit import statements into the user's AST that retrieve the active profiler from a safe, module-level accessor.Tasks:
ferret/core.py):_global_profiler.set_global_profiler(profiler)andget_global_profiler().ferret/cli.py):FerretInstrumentorto stop assuming_ferret_profilerexists in builtins._inject_decoratorlogic to insert a localized import at the top of the instrumented function or module (e.g.,from ferret.core import get_global_profiler).@get_global_profiler().measure(...).FerretInstrumentorto visitast.Lambdanodes and wrap them in a profiling context, as these are currently ignored.Acceptance Criteria:
ferret run script.pyworks withoutbuiltins._ferret_profilerbeing present in thelocals()orglobals()of the user script._ferret_profilervariable do not cause the profiler to crash.