Skip to content

app_model #

Generic application schema implemented in python.

Action #

Bases: CommandRule, Generic[P, R]

An Action is a callable object with menu placement, keybindings, and metadata.

This is the "complete" representation of a command. Including a pointer to the actual callable object, as well as any additional menu and keybinding rules. Most commands and menu items will be represented by Actions, and registered using register_action.

Parameters:

  • callback (Callable[~P, ~R] | str) –

    A function to call when the associated command id is executed. If a string is provided, it must be a fully qualified name to a callable python object. This usually takes the form of {obj.__module__}:{obj.__qualname__} (e.g. my_package.a_module:some_function)

  • menus (List[MenuRule] | None, default: None ) –

    (Optional) Menus to which this action should be added. Note that menu items in the sequence may be supplied as a plain string, which will be converted to a MenuRule with the string as the id field.

  • keybindings (List[KeyBindingRule] | None, default: None ) –

    (Optional) Default keybinding(s) that will trigger this command.

  • palette (bool, default: True ) –

    Whether to add this command to the global Command Palette during registration.

Application #

Application(name: str, *, raise_synchronous_exceptions: bool = False, commands_reg_class: Type[CommandsRegistry] = CommandsRegistry, menus_reg_class: Type[MenusRegistry] = MenusRegistry, keybindings_reg_class: Type[KeyBindingsRegistry] = KeyBindingsRegistry, injection_store_class: Type[ino.Store] = ino.Store, context: Context | MutableMapping | None = None)

Full application model.

This is the top level object that comprises all of the registries, and other app-namespace specific objects.

Parameters:

  • name (str) –

    A name for this application.

  • raise_synchronous_exceptions (bool, default: False ) –

    Whether to raise exceptions that occur while executing commands synchronously, by default False. This is settable after instantiation, and can also be controlled per execution by calling result.result() on the future object returned from the execute_command method.

  • commands_reg_class (Type[CommandsRegistry], default: CommandsRegistry ) –

    (Optionally) override the class to use when creating the CommandsRegistry

  • menus_reg_class (Type[MenusRegistry], default: MenusRegistry ) –

    (Optionally) override the class to use when creating the MenusRegistry

  • keybindings_reg_class (Type[KeyBindingsRegistry], default: KeyBindingsRegistry ) –

    (Optionally) override the class to use when creating the KeyBindingsRegistry

  • injection_store_class (Type[Store], default: Store ) –

    (Optionally) override the class to use when creating the injection Store

  • context (Context | MutableMapping | None, default: None ) –

    (Optionally) provide a context to use for this application. If a MutableMapping is provided, it will be used to create a Context instance. If None (the default), a new Context instance will be created.

Attributes:

  • commands (CommandsRegistry) –

    The Commands Registry for this application.

  • menus (MenusRegistry) –

    The Menus Registry for this application.

  • keybindings (KeyBindingsRegistry) –

    The KeyBindings Registry for this application.

  • injection_store (Store) –

    The Injection Store for this application.

  • context (Context) –

    The Context for this application.

Source code in app_model/_app.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
def __init__(
    self,
    name: str,
    *,
    raise_synchronous_exceptions: bool = False,
    commands_reg_class: Type[CommandsRegistry] = CommandsRegistry,
    menus_reg_class: Type[MenusRegistry] = MenusRegistry,
    keybindings_reg_class: Type[KeyBindingsRegistry] = KeyBindingsRegistry,
    injection_store_class: Type[ino.Store] = ino.Store,
    context: Context | MutableMapping | None = None,
) -> None:
    self._name = name
    if name in Application._instances:
        raise ValueError(
            f"Application {name!r} already exists. Retrieve it with "
            f"`Application.get_or_create({name!r})`."
        )
    Application._instances[name] = self

    if context is None:
        context = Context()
    elif isinstance(context, MutableMapping):
        context = Context(context)
    if not isinstance(context, Context):
        raise TypeError(
            f"context must be a Context or MutableMapping, got {type(context)}"
        )
    self._context = context
    self._context.update(app_model_context())

    self._context["is_linux"] = sys.platform.startswith("linux")
    self._context["is_mac"] = sys.platform == "darwin"
    self._context["is_windows"] = os.name == "nt"

    self._injection_store = injection_store_class.create(name)
    self._commands = commands_reg_class(
        self.injection_store,
        raise_synchronous_exceptions=raise_synchronous_exceptions,
    )
    self._menus = menus_reg_class()
    self._keybindings = keybindings_reg_class()

    self.injection_store.on_unannotated_required_args = "ignore"

    self._disposers: List[Tuple[str, DisposeCallable]] = []

commands property #

commands: CommandsRegistry

Return the CommandsRegistry.

context property #

context: Context

Return the Context for this application.

injection_store property #

injection_store: ino.Store

Return the in_n_out.Store instance associated with this Application.

keybindings property #

keybindings: KeyBindingsRegistry

Return the KeyBindingsRegistry.

menus property #

menus: MenusRegistry

Return the MenusRegistry.

name property #

name: str

Return the name of this Application.

raise_synchronous_exceptions property writable #

raise_synchronous_exceptions: bool

Whether to raise synchronous exceptions.

destroy classmethod #

destroy(name: str) -> None

Destroy the Application named name.

This will call dispose(), destroy the injection store, and remove the application from the list of stored application names (allowing the name to be reused).

Source code in app_model/_app.py
180
181
182
183
184
185
186
187
188
189
190
191
192
193
@classmethod
def destroy(cls, name: str) -> None:
    """Destroy the `Application` named `name`.

    This will call [`dispose()`][app_model.Application.dispose], destroy the
    injection store, and remove the application from the list of stored
    application names (allowing the name to be reused).
    """
    if name not in cls._instances:
        return  # pragma: no cover
    app = cls._instances.pop(name)
    app.dispose()
    app.injection_store.destroy(name)
    app.destroyed.emit(app.name)

dispose #

dispose() -> None

Dispose this Application.

This calls all disposers functions (clearing all registries).

Source code in app_model/_app.py
203
204
205
206
207
208
209
210
def dispose(self) -> None:
    """Dispose this `Application`.

    This calls all disposers functions (clearing all registries).
    """
    while self._disposers:
        with contextlib.suppress(Exception):
            self._disposers.pop()[1]()

get_app classmethod #

get_app(name: str) -> Optional[Application]

Return app named name or None if it doesn't exist.

Source code in app_model/_app.py
175
176
177
178
@classmethod
def get_app(cls, name: str) -> Optional[Application]:
    """Return app named `name` or None if it doesn't exist."""
    return cls._instances.get(name)

get_or_create classmethod #

get_or_create(name: str) -> Application

Get app named name or create and return a new one if it doesn't exist.

Source code in app_model/_app.py
170
171
172
173
@classmethod
def get_or_create(cls, name: str) -> Application:
    """Get app named `name` or create and return a new one if it doesn't exist."""
    return cls._instances[name] if name in cls._instances else cls(name)

register_action #

register_action(action: str | Action, title: str | None = None, *, callback: CommandCallable | None = None, category: str | None = None, tooltip: str | None = None, icon: IconOrDict | None = None, enablement: Expr | None = None, menus: list[MenuRuleOrDict] | None = None, keybindings: list[KeyBindingRuleOrDict] | None = None, palette: bool = True) -> CommandDecorator | DisposeCallable

Register Action instance with this application.

An Action is the complete representation of a command, including information about where and whether it appears in menus and optional keybinding rules.

See register_action for complete details on this function.

Source code in app_model/_app.py
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
def register_action(
    self,
    action: str | Action,
    title: str | None = None,
    *,
    callback: CommandCallable | None = None,
    category: str | None = None,
    tooltip: str | None = None,
    icon: IconOrDict | None = None,
    enablement: Expr | None = None,
    menus: list[MenuRuleOrDict] | None = None,
    keybindings: list[KeyBindingRuleOrDict] | None = None,
    palette: bool = True,
) -> CommandDecorator | DisposeCallable:
    """Register [`Action`][app_model.Action] instance with this application.

    An [`Action`][app_model.Action] is the complete representation of a command,
    including information about where and whether it appears in menus and optional
    keybinding rules.

    See [`register_action`][app_model.register_action] for complete
    details on this function.
    """
    if isinstance(action, Action):
        return register_action(self, action)

    return register_action(
        self,
        id_or_action=action,
        title=title,  # type: ignore
        callback=callback,  # type: ignore
        category=category,
        tooltip=tooltip,
        icon=icon,
        enablement=enablement,
        menus=menus,
        keybindings=keybindings,
        palette=palette,
    )

register_actions #

register_actions(actions: Iterable[Action]) -> DisposeCallable

Register multiple Action instances with this app.

Returns a function that may be called to undo the registration of actions.

Source code in app_model/_app.py
287
288
289
290
291
292
293
294
295
296
297
298
def register_actions(self, actions: Iterable[Action]) -> DisposeCallable:
    """Register multiple [`Action`][app_model.Action] instances with this app.

    Returns a function that may be called to undo the registration of `actions`.
    """
    d = [self.register_action(action) for action in actions]

    def _dispose() -> None:
        while d:
            d.pop()()

    return _dispose

register_action #

register_action(app: Application | str, id_or_action: str | Action, title: str | None = None, *, callback: CommandCallable | None = None, category: str | None = None, tooltip: str | None = None, icon: IconOrDict | None = None, enablement: expressions.Expr | None = None, menus: list[MenuRuleOrDict] | None = None, keybindings: list[KeyBindingRuleOrDict] | None = None, palette: bool = True) -> CommandDecorator | DisposeCallable

Register an action.

This is a functional form of the Application.register_action() method. It accepts various overloads to allow for a more concise syntax. See examples below.

An Action is the "complete" representation of a command. The command is the function/callback itself, and an action also includes information about where and whether it appears in menus and optional keybinding rules. Since, most of the arguments to this function are simply passed through to the Action constructor, see also docstrings for:

Parameters:

  • app (Application | str) –

    The app in which to register the action. If a string, the app is retrieved or created as necessary using Application.get_or_create(app).

  • id_or_action (str | Action) –

    Either a complete Action object or a string id of the command being registered. If an Action object is provided, then all other arguments are ignored.

  • title (str | None, default: None ) –

    Title by which the command is represented in the UI. Required when id_or_action is a string.

  • callback (CommandHandler | None, default: None ) –

    Callable object that executes this command, by default None. If not provided, a decorator is returned that can be used to decorate a function that executes this action.

  • category (str | None, default: None ) –

    Category string by which the command may be grouped in the UI, by default None

  • tooltip (str | None, default: None ) –

    Tooltip to show when hovered., by default None

  • icon (Icon | None, default: None ) –

    Icon used to represent this command, e.g. on buttons or in menus. by default None

  • enablement (Expr | None, default: None ) –

    Condition which must be true to enable the command in in the UI, by default None

  • menus (list[MenuRuleOrDict] | None, default: None ) –

    List of MenuRule or kwarg dicts containing menu placements for this action, by default None

  • keybindings (list[KeyBindingRuleOrDict] | None, default: None ) –

    List of KeyBindingRule or kwargs dicts containing default keybindings for this action, by default None

  • palette (bool, default: True ) –

    Whether to adds this command to the Command Palette, by default True

Returns:

  • CommandDecorator

    If callback is not provided, then a decorator is returned that can be used to decorate a function as the executor of the command.

  • DisposeCallable

    If callback is provided, or id_or_action is an Action object, then a function is returned that may be used to unregister the action.

Raises:

  • ValueError

    If id_or_action is a string and title is not provided.

  • TypeError

    If id_or_action is not a string or an Action object.

Examples:

This function can be used directly or as a decorator, and accepts arguments in various forms.

Passing an existing Action object#

When the id_or_action argument is an instance of app_model.Action, then all other arguments are ignored, the action object is registered directly, and the return value is a function that may be used to unregister the action is returned.

from app_model import Application, Action, register_action

app = Application.get_or_create("myapp")
action = Action("my_action", title="My Action", callback=lambda: print("hi"))
register_action(app, action)

app.commands.execute_command("my_action")  # prints "hi"

Creating a new Action#

When the id_or_action argument is a string, it is interpreted as the id of the command being registered, in which case title must then also be provided. All other arguments are optional, but may be used to customize the action being created (with keybindings, menus, icons, etc).

register_action(
    app,
    "my_action2",
    title="My Action2",
    callback=lambda: print("hello again!"),
)

app.commands.execute_command("my_action2")  # prints "hello again!"

Usage as a decorator#

If callback is not provided, then a decorator is returned that can be used decorate a function as the executor of the command:

@register_action(app, "my_action3", title="My Action3")
def my_action3():
    print("hello again, again!")


app.commands.execute_command("my_action3")  # prints "hello again, again!"

Passing app as a string#

Note that in all of the above examples, the first app argument may be either an instance of an Application object, or a string name of an application. If a string is provided, then the application is retrieved or created as necessary using Application.get_or_create().

register_action(
    "myapp",  # app name instead of Application instance
    "my_action4",
    title="My Action4",
    callback=lambda: print("hello again, again, again!"),
)
Source code in app_model/registries/_register.py
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
def register_action(
    app: Application | str,
    id_or_action: str | Action,
    title: str | None = None,
    *,
    callback: CommandCallable | None = None,
    category: str | None = None,
    tooltip: str | None = None,
    icon: IconOrDict | None = None,
    enablement: expressions.Expr | None = None,
    menus: list[MenuRuleOrDict] | None = None,
    keybindings: list[KeyBindingRuleOrDict] | None = None,
    palette: bool = True,
) -> CommandDecorator | DisposeCallable:
    """Register an action.

    This is a functional form of the
    [`Application.register_action()`][app_model.Application.register_action] method.
    It accepts various overloads to allow for a more concise syntax.  See examples
    below.

    An `Action` is the "complete" representation of a command.  The command is the
    function/callback itself, and an action also includes information about where and
    whether it appears in menus and optional keybinding rules.  Since, most of the
    arguments to this function are simply passed through to the `Action` constructor,
    see also docstrings for:

    - [`Action`][app_model.types.Action]
    - [`CommandRule`][app_model.types.CommandRule]
    - [`MenuRule`][app_model.types.MenuRule]
    - [`KeyBindingRule`][app_model.types.KeyBindingRule]

    Parameters
    ----------
    app: Application | str
        The app in which to register the action. If a string, the app is retrieved
        or created as necessary using
        [`Application.get_or_create(app)`][app_model.Application.get_or_create].
    id_or_action : str | Action
        Either a complete Action object or a string id of the command being registered.
        If an `Action` object is provided, then all other arguments are ignored.
    title : str | None
        Title by which the command is represented in the UI. Required when
        `id_or_action` is a string.
    callback : CommandHandler | None
        Callable object that executes this command, by default None. If not provided,
        a decorator is returned that can be used to decorate a function that executes
        this action.
    category : str | None
        Category string by which the command may be grouped in the UI, by default None
    tooltip : str | None
        Tooltip to show when hovered., by default None
    icon : Icon | None
        [`Icon`][app_model.types.Icon] used to represent this command,
        e.g. on buttons or in menus. by default None
    enablement : expressions.Expr | None
        Condition which must be true to enable the command in in the UI,
        by default None
    menus : list[MenuRuleOrDict] | None
        List of [`MenuRule`][app_model.types.MenuRule] or kwarg `dicts` containing menu
        placements for this action, by default None
    keybindings : list[KeyBindingRuleOrDict] | None
        List of [`KeyBindingRule`][app_model.types.KeyBindingRule] or kwargs `dicts`
        containing default keybindings for this action, by default None
    palette : bool
        Whether to adds this command to the Command Palette, by default True

    Returns
    -------
    CommandDecorator
        If `callback` is not provided, then a decorator is returned that can be used to
        decorate a function as the executor of the command.
    DisposeCallable
        If `callback` is provided, or `id_or_action` is an `Action` object, then a
        function is returned that may be used to unregister the action.

    Raises
    ------
    ValueError
        If `id_or_action` is a string and `title` is not provided.
    TypeError
        If `id_or_action` is not a string or an `Action` object.

    Examples
    --------
    This function can be used directly or as a decorator, and accepts arguments in
    various forms.

    ## Passing an existing Action object

    When the `id_or_action` argument is an instance of `app_model.Action`, then
    all other arguments are ignored, the action object is registered directly, and the
    return value is a function that may be used to unregister the action is returned.

    ```python
    from app_model import Application, Action, register_action

    app = Application.get_or_create("myapp")
    action = Action("my_action", title="My Action", callback=lambda: print("hi"))
    register_action(app, action)

    app.commands.execute_command("my_action")  # prints "hi"
    ```

    ## Creating a new Action

    When the `id_or_action` argument is a string, it is interpreted as the `id`
    of the command being registered, in which case `title` must then also be provided.
    All other arguments are optional, but may be used to customize the action being
    created (with keybindings, menus, icons, etc).

    ```python
    register_action(
        app,
        "my_action2",
        title="My Action2",
        callback=lambda: print("hello again!"),
    )

    app.commands.execute_command("my_action2")  # prints "hello again!"
    ```

    ## Usage as a decorator

    If `callback` is not provided, then a decorator is returned that can be used
    decorate a function as the executor of the command:

    ```python
    @register_action(app, "my_action3", title="My Action3")
    def my_action3():
        print("hello again, again!")


    app.commands.execute_command("my_action3")  # prints "hello again, again!"
    ```

    ## Passing app as a string

    Note that in all of the above examples, the first `app` argument may be either an
    instance of an [`Application`][app_model.Application] object, or a string name of
    an application.  If a string is provided, then the application is retrieved or
    created as necessary using
    [`Application.get_or_create()`][app_model.Application.get_or_create].

    ```python
    register_action(
        "myapp",  # app name instead of Application instance
        "my_action4",
        title="My Action4",
        callback=lambda: print("hello again, again, again!"),
    )
    ```
    """
    if isinstance(id_or_action, Action):
        return _register_action_obj(app, id_or_action)
    if isinstance(id_or_action, str):
        if not title:
            raise ValueError("'title' is required when 'id' is a string")
        return _register_action_str(
            app=app,
            id=id_or_action,
            title=title,
            category=category,
            tooltip=tooltip,
            icon=icon,
            enablement=enablement,
            callback=callback,
            palette=palette,
            menus=menus,
            keybindings=keybindings,
        )
    raise TypeError("'id_or_action' must be a string or an Action")