yera.apps.discovery

Utilities for loading apps from files.

Symbols

def discover_apps — Discover all apps in a directory.
def load_app — Load a Python file and extract the AppFunctionWrapper instance with the given identifier.
def load_apps — Load a Python file and extract all AppFunctionWrapper instances.
def path_to_module_name — Convert a Python file path to a dotted module name for tools and apps.

discover_apps

discover_apps(
    directory: Path | str,
    id_anchor: Path | None = None,
) → list[AppFunctionWrapper]

Discover all apps in a directory.

Scans the directory tree for .py files and loads all apps from each file. Hidden directories (names starting with .) are not entered, so typical trees like .venv or .git are skipped.

This function underpins the /api/apps endpoint exposed by the dev server: the React UI queries /api/apps to build the home page and to resolve app_id strings used in /apps/{id} routes. Running yera dev in different directories will therefore expose different sets of apps to the same static UI bundle.

Parameters

directory
type: Path | str

Directory to scan for app files.

id_anchor
type: Path | None = None

Root directory used to compute dotted module names for app identifiers. Defaults to the project root (directory of the nearest pyproject.toml walking up from cwd), falling back to directory itself when no pyproject.toml is found.

Returns

type: list[AppFunctionWrapper]

List of appFunctionWrapper instances.

Raises

FileNotFoundError

If the directory does not exist.

load_app

load_app(
    file_path: Path | str,
    app_identifier: str | None = None,
) → AppFunctionWrapper

Load a Python file and extract the AppFunctionWrapper instance with the given identifier.

Parameters

file_path
type: Path | str

Path to the Python file containing one or more apps. Can be a Path object or string.

app_identifier
type: str | None = None

Identifier of the app to load. If None, the first app is loaded.

Returns

type: AppFunctionWrapper

AppFunctionWrapper instance.

Raises

ValueError

If no apps are found in the file.

ValueError

If multiple apps are found in the file and no identifier is provided.

ValueError

If the specified app identifier is not found in the file.

ValueError

If the specified app identifier does not match the identifier of the loaded app.

load_apps

load_apps(
    file_path: Path | str,
    base_dir: Path | None = None,
) → list[AppFunctionWrapper]

Load a Python file and extract all AppFunctionWrapper instances.

This helper looks for objects in the module that are instances of AppFunctionWrapper (created by the @yr.app decorator).

Parameters

file_path
type: Path | str

Path to the Python file containing one or more apps. Can be a Path object or string.

base_dir
type: Path | None = None

Root directory used to compute the module name for app identifiers. Defaults to the current working directory.

Returns

type: list[AppFunctionWrapper]

Dictionary mapping app identifiers to AppFunctionWrapper instances.

Raises

FileNotFoundError

If the file does not exist.

path_to_module_name

path_to_module_name(
    path: Path,
    base_dir: Path | None = None,
) → str

Convert a Python file path to a dotted module name for tools and apps.

This helper is used anywhere we need a stable module identifier for dynamically loaded code (e.g. CLI-loaded apps, tools discovered from the filesystem).

Behaviour: - Strips the .py suffix from the path. - If the file is under the given base_dir (or current working directory when base_dir is None), it converts the relative path into a dotted module name, using each directory component as a segment. - If the file is not under base_dir, it falls back to the filename stem.

Examples

  • path: /repo/demos/apps/basic_chatbot.py, base_dir=/repo -> "demos.apps.basic_chatbot"
  • path: /tmp/basic_chatbot.py, base_dir=/repo -> "basic_chatbot"