Description
Classification:
Enhancement
Version
AutoKey version: All < 0.96
Summary
When importing modules, the imported module has no access to the AutoKey scripting API.
This is particularly problematic for custom modules added to the import path, using the user module setting in the AK settings. Users expect that they can use the API function without additional hops, like writing and calling custom injector functions inside their imported module.
Steps to Reproduce (if applicable)
- Set the custom module search path in the AK settings.
- Write a module that calls API functions and place it there
import
the module inside a script- Try to run functions from the imported module
Expected Results
- Everything works
Actual Results
- import fails, if the import executes API calls at the module top level
- calling functions fails with an
AttributeError
(or UnboundLocalError?), if the function internally calls AK API functions
Notes
@josephj11 Here is the enhancement issue you asked about in #246.
Workaround
Add an injection function like this to the module requiring the API: Gitter chat reference
def load_api(api_keyboard, api_mouse, api_store, api_system, api_window, api_clipboard, api_highlevel, api_dialog, api_engine):
global keyboard, mouse, store, system, window, clipboard, highlevel, dialog, engine # Define the API class instances as globals
# then put the given instances into the script globals
keyboard = api_keyboard
mouse = api_mouse
store = api_store
system = api_system
window = api_window
clipboard = api_clipboard
highlevel = api_highlevel
dialog = api_dialog
engine = api_engine
In the AutoKey script, import the module like this:
import my_module
my_module.load_api(keyboard, mouse, store, system, window, clipboard, highlevel, dialog, engine)
Implementation notes
Implementing this requires to overwrite the import statement. It should inject the API objects into the global module state, preferably at the beginning of the module execution, so top-level API calls work.
If that does not work, it should at least add the objects after execution, before returning the module object.
This injection should be optional to not disturb modules that don’t expect this. The AK API object names are sufficiently normal to be able to cause issue. Add another API call, like engine.enable_injecting_api_on_import()
, which has to be called before importing modules to enable the injection mechanism.