composeui.core.reload

--reload for a desktop app: a supervisor runs the program in a child process.

On a change, the supervisor sends the app the files changed. The app saves its views’ state and its model’s data (a study), runs the program’s changed code again in place (rerun_program), and opens the study in the new app, so its window stays as it was left. When the app can’t, e.g. ComposeUI itself changed, it exits instead, and the supervisor runs the program again in a new child process, which opens the study.

composeui.core.reload.acknowledge_changes()[source]

Tell the supervisor the app runs the changed code, so it keeps the app running.

Return type:

None

composeui.core.reload.can_reload_in_place(changed)[source]

Tell whether the app can run the code of the files changed without a new process.

Not when ComposeUI’s own code changed: the running app’s objects keep its old classes.

Parameters:

changed (Sequence[Path])

Return type:

bool

composeui.core.reload.has_change_events(directory)[source]

Tell whether the system reports the changes under directory.

On WSL, it doesn’t for a Windows drive’s files, under /mnt: they’re polled.

Parameters:

directory (Path)

Return type:

bool

composeui.core.reload.is_reloaded()[source]

Tell whether this process is the app a --reload supervisor runs.

Return type:

bool

composeui.core.reload.keep_rerun(run)[source]

Keep run, an app ready to run, if rerun_program runs the program, and end it.

An app’s run calls it before it runs. The program ends there, as when the app runs, so the code after run doesn’t run on a reload either.

Parameters:

run (object)

Return type:

None

composeui.core.reload.load_reloaded_state(main_view, model, directory=None)[source]

Open the state the previous run saved, if any and if it still fits the app.

From directory, else the one the supervisor shares with the app.

Parameters:
  • main_view (MainView)

  • model (Model | None)

  • directory (Path | None)

Return type:

None

composeui.core.reload.program_command()[source]

Build the command running this program again: the script, or the -m module.

Return type:

list[str]

composeui.core.reload.rerun_program()[source]

Run the program again in this process, its code imported afresh; return its app.

The modules of its code (_is_program_module) are imported again. The app the program runs is kept, unrun (keep_rerun). On an error, e.g. a syntax error, or when no app is kept, the program’s previous modules come back and the error is raised.

Return type:

Any

composeui.core.reload.run_reloading(command=None, changes=None)[source]

Run command, the program by default, and run it again whenever a Python file changes.

It returns once the app exits by itself without an error, e.g. its window is closed. An app that fails, e.g. on a syntax error, runs again only on the next change. On a change, the running app is asked to run the changed code (take_changes); if it exits instead, or doesn’t take the files changed, it runs again in a new process.

Parameters:
  • command (Sequence[str] | None)

  • changes (Iterator[set[Path]] | None)

Return type:

int

composeui.core.reload.save_reloaded_state(main_view, model, directory=None)[source]

Save the views’ state and the model’s data, for the next run to open.

Into directory, an existing one, else the one the supervisor shares with the app.

Parameters:
  • main_view (MainView)

  • model (Model | None)

  • directory (Path | None)

Return type:

None

composeui.core.reload.take_changes()[source]

Take the files changed, if the supervisor asks the app to run their code.

Taken, they tell the supervisor to wait for the app, until acknowledge_changes.

Return type:

list[Path] | None

composeui.core.reload.watch_changes(directory)[source]

Watch the Python files under directory from now on, and yield those changed.

The generator yields every step, often none, the files’ paths resolved. With watchfiles installed, the system tells about changes; else, or when it can’t, the files are polled. Close it to stop watching.

Parameters:

directory (Path)

Return type:

Generator[set[Path], None, None]