# Getting started ## Project structure ``` my_project/ ├── main.py ├── config.ini └── modules/ ├── cmds_foo.py └── cmds_bar.py ``` ## Configuration file ```ini [general] default = foo # default module (used when no module is specified) # methods_prefix = cmd_ # optional: override command method prefix # modules_prefix = cmds_ # optional: override module file prefix [foo] alias = f # optional: short name for the module my_setting = value # any key accessible via self.config.get("my_setting") [bar] # ... ``` ## Writing a module ```python from appengine import Commands, AppEngineException, AEErrs class Foo(Commands): # Set to True to run this module in a background thread threaded = False # Declare dependencies on other modules # dependencies = ["bar"] # list form → self.bar = cmods["bar"] # dependencies = {"b": "bar"} # dict form → self.b = cmods["bar"] def cmd_add(self, a: float, b: float): """Add two numbers. Args: a: First operand. b: Second operand. Returns: float: The sum of *a* and *b*. """ return float(a) + float(b) def cmd_fail(self): """Demonstrate structured error reporting.""" raise AppEngineException(AEErrs.INVALID_PARAMS, "Nothing to do here") def free(self): # Close connections, files, etc. pass ``` ## Threaded module ```python import time from appengine import Commands class Worker(Commands): threaded = True # will be started as a Thread def run(self): while not self.stopped: self.info("tick") time.sleep(1) def free(self): self.info("worker cleaned up") ``` ## Dispatching commands Commands are dispatched via `execute_command(module, method, *args)`: ```python success, result = my_commands_instance.execute_command("foo", "add", 1, 2) ``` ### Built-in help | Call | Result | |------|--------| | `execute_command("", "help")` | List of all modules | | `execute_command("", "help", "foo")` | List of commands in `foo` | | `execute_command("", "help", "foo.add")` | Docstring of `foo.add` | ## Error handling Commands return `(success: bool, result)`. On error, `result` is a tuple `(error_code: int, message: str)`. Error codes follow the JSON-RPC convention (see `AEErrs`).