8000 Scripting API: Overwrite `import` semantics to inject API functions into user modules · Issue #248 · autokey/autokey · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
Scripting API: Overwrite import semantics to inject API functions into user modules #248
Open
@luziferius

Description

@luziferius

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0