Applying decorator to function appears to remove it from module __dict__

136 views Asked by At

I am defining several functions in a python package composed of several modules that represent separate components of a simulation model.

To execute the simulation model, the package is imported and the functions along with their __name__ are extracted by iterating through the modules' __dict__ like this:

import model # The package containing python modules

import inspect
import types

# Get the modules defined in the package
modules = [v for v in vars(model).values() if isinstance(v, types.ModuleType)]

funcs = {}

# Iterate through modules in python package
for module in modules:
    # Go through objects in module `__dict__`
    for name, obj in vars(module).items():  # decorated functions no longer appear here
        # Check for functions
        if isinstance(obj, types.FunctionType):
            # Make sure that the function is defined within the model package
            mod, *sub_mod = inspect.getmodule(obj).__name__.split('.')
            if mod == model.__name__:
                # Store the function along with its name
                funcs[name] = obj

However, when I am debugging this code I'm noticing that some functions that should be in vars(module).items() are not. This happened after applying an lru_cache decorator to some of the functions, which are precisely the ones not showing up.

Why after applying a decorator to some of the functions in the python package do they not show up in the module's __dict__ for which they are defined?

Is there a way to still be able to apply the decorator and have the functions show up in vars(module).items()?

1

There are 1 answers

0
mwchase On BEST ANSWER

The problem is that when you wrap a function with lru_cache, the result is only a callable object, and not a function. The precise type is functools._lru_cache_wrapper.

I originally posted this as a comment. pbreach's solution was to replace types.FunctionType with (types.FunctionType, functools._lru_cache_wrapper), because callable() was too broad a net.