{"id":9482,"library":"app-model","title":"app-model: Generic Application Schema","description":"app-model is a Python library that provides a generic application schema, inspired by frameworks like VS Code and Qt. It allows defining commands, menus, keybindings, and application state in a structured, framework-agnostic way. Built on Pydantic, it offers strong typing and data validation. The current version is 0.5.1, with releases typically tied to feature development and bug fixes.","status":"active","version":"0.5.1","language":"en","source_language":"en","source_url":"https://github.com/pyapp-kit/app-model","tags":["application","schema","commands","menus","pydantic","declarative"],"install":[{"cmd":"pip install app-model","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core dependency for data modeling, validation, and serialization. Requires Pydantic v2.x.","package":"pydantic","optional":false}],"imports":[{"symbol":"Application","correct":"from app_model import Application"},{"symbol":"Command","correct":"from app_model import Command"},{"symbol":"Menu","correct":"from app_model import Menu"},{"symbol":"SubMenu","correct":"from app_model import SubMenu"},{"note":"Action is part of the `types` submodule, not directly under `app_model`.","wrong":"from app_model import Action","symbol":"Action","correct":"from app_model.types import Action"}],"quickstart":{"code":"from app_model import Application, Command, Menu\n\ndef say_hello(name: str = \"World\") -> str:\n    \"A command that greets the provided name.\"\n    return f\"Hello, {name}!\"\n\ndef say_goodbye() -> str:\n    \"A simple command to say goodbye.\"\n    return \"Goodbye!\"\n\n# 1. Initialize the application\napp = Application(\"my-first-app\")\n\n# 2. Register commands\napp.register_command(Command(\"my-app.hello\", say_hello, title=\"Say Hello\"))\napp.register_command(Command(\"my-app.goodbye\", say_goodbye, title=\"Say Goodbye\"))\n\n# 3. Register a menu item for the 'hello' command\napp.register_menu_item(\n    Menu.APP,  # or Menu.FILE, Menu.EDIT, etc.\n    Command(\"my-app.hello\", title=\"Say Hello from Menu\", menu_path=\"File > Hello\"),\n)\n\n# 4. Execute a command and get its result\nhello_result = app.commands.execute(\"my-app.hello\", {\"name\": \"Registry\"}).result()\nprint(f\"Hello Command Result: {hello_result}\")\n\ngoodbye_result = app.commands.execute(\"my-app.goodbye\").result()\nprint(f\"Goodbye Command Result: {goodbye_result}\")","lang":"python","description":"This quickstart demonstrates how to set up a basic `Application`, define and register commands using `Command` objects, associate them with menus via `Menu` enumerations, and execute commands, retrieving their results. Note the use of `.result()` to unwrap the `Future` returned by `execute` for synchronous retrieval."},"warnings":[{"fix":"Ensure `pydantic>=2.0` is installed in your environment: `pip install 'pydantic>=2'`.","message":"app-model v0.4.0+ requires Pydantic v2.0 or newer. Using Pydantic v1.x will lead to `ValidationError` or `AttributeError` issues, particularly when models are instantiated or validated.","severity":"breaking","affected_versions":">=0.4.0"},{"fix":"Always append `.result()` for synchronous calls: `app.commands.execute(...).result()`. For async functions, use `await app.commands.execute(...)`.","message":"The `app.commands.execute()` method returns a `Future` object, not the direct result of the command. If you need the result immediately in a synchronous context, you must call `.result()` on the returned Future. In an `async` context, `await` the Future.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Update your menu registration code to use the direct `Menu` enum members, e.g., `Menu.APP` instead of `MenuType.APP` or string literal names.","message":"The `Menu` enums were refactored in v0.5.0. If you were previously using patterns like `MenuType.APP`, these have been simplified to `Menu.APP`. Direct `Menu` enum members are now used for registering menu items.","severity":"gotcha","affected_versions":">=0.5.0"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Upgrade Pydantic to version 2.0 or newer: `pip install 'pydantic>=2'`.","cause":"You are likely running `app-model` with Pydantic v1.x installed, which is incompatible with recent versions of `app-model` (v0.4.0+).","error":"pydantic.v1.error_wrappers.ValidationError: ..."},{"fix":"Modify your command execution to retrieve the actual result: `result = app.commands.execute('my-app.command_id').result()`.","cause":"You forgot to call `.result()` on the `Future` object returned by `app.commands.execute()`, attempting to access attributes directly on the Future itself.","error":"AttributeError: 'Future' object has no attribute 'my_expected_attribute'"},{"fix":"Ensure the command ID matches exactly one of your registered commands. Verify the ID in `app.register_command(Command('YOUR_ID', ...))` and `app.commands.execute('YOUR_ID', ...)`.","cause":"The command ID provided to `app.commands.execute()` or `app.register_menu_item()` does not correspond to any command that has been registered with the `Application` instance.","error":"app_model.types.CommandNotFoundError: Command 'unknown_id' not found"}]}