LiveImport API

liveimport.register(namespace: dict[str, Any], importstmts: str, *, package: str = '', clear: bool = False, allow_other_statements: bool = False) None

Register import statements for syncing.

All modules referenced by the import statements must already be loaded and have associated source files, and all names mentioned must already exist in namespace. If an associated source file is later modified, then a sync will reload the corresponding module and update names from the module.

Parameters:
  • namespace – The import statement target, usually the caller’s value of globals().

  • importstmts – Python code consisting of zero or more import statements. The application should have already executed these or equivalent imports.

  • package – Context for interpreting relative import statements. When given, package is usually the caller’s immediate parent package, accessible as __spec__.parent if it exists. If no package is specified, relative imports are not allowed. Relative imports are only useful when using LiveImport outside a notebook, since notebook code is not in a package.

  • clear – If and only if true, discard all prior registrations targeting namespace before registering the given import statements.

  • allow_other_statements – If true, non-import statements are allowed in importstmts and ignored. Otherwise, only import statements are allowed.

Raises:
  • SyntaxErrorimportstmts is not syntactically valid.

  • ImportErrorimportstmts includes an improper relative import.

  • ValueErrorimportstmts includes a non-import statement and allow_other_statements is false, a referenced module is not loaded or has no associated source file, or an included name does not already exist.

  • ModuleError – The content of a module referenced by an import statement is erroneous.

Example:

liveimport.register(globals(),"""
import printmath as pm
from simulator import stop as halt
from verify import *
""")

If verify.py is modified, a sync will reload verify and create or update bindings in namespace for the same names that executing from verify import * would. Similarly, if simulator.py is modified, a sync will reload the module and create or update a binding for halt with the value of stop in simulator.

Using multiline strings to specify multiple import statements, each on its own line as shown above is convenient and easy to read, but statements must have identical indentation.

# Raises a SyntaxError because "import green" has leading whitespace
# while "import red" does not.
liveimport.register(globals(),"""import red
    import green""")

# This works.
liveimport.register(globals(),"""import red
import green""")

# And so does this.
liveimport.register(globals(),"""
    import red
    import green""")

Since the statements given are Python code, you can also use semicolons to separate statements.

liveimport.register(globals(),"import red; import green")

Registration is idempotent, multiple registrations are allowed, and overlapping registrations such as

liveimport.register(globals(),"from symcode import x, hermite_poly")
liveimport.register(globals(),"from symcode import x, lagrange_poly")
liveimport.register(globals(),"from symcode import lagrange_poly as lp")
liveimport.register(globals(),"from symcode import *")
liveimport.register(globals(),"import symcode")

are perfectly fine.

liveimport.sync(*, observer: Callable[[ReloadEvent], None] | None = None) None

Bring all registered imports up to date. This includes reloading out-of-date tracked modules and rebinding imported names. A tracked module is out-of-date if either the module has changed since registration or last sync, or the module depends on an out-of-date tracked module.

“Depends on” is a strict partial order LiveImport computes between tracked modules based on the top level import statements in those modules. In most cases, those imports naturally define a strict partial order. If they do not (meaning there is an import cycle), LiveImport ignores the imports by more recently tracked modules that prevent it.

sync() guarantees that reload order is consistent with the “depends on” partial order, so if A depends on B, then B will reload before A.

sync() uses source file modification times to determine if a module has changed. Any change triggers a reload, including being reset to an older time. (So reverted modules reload.)

Parameters:

observer – If given, sync() calls observer with a ReloadEvent describing each successful reload.

Raises:

ModuleError – The content of a tracked module is erronous or raised an exception when executed during a reload.

Note

Unless automatic syncing is disabled, calling sync() in a notebook should not be necessary.

liveimport.workspace(*directories: str | PathLike) None

Define the workspace, a set of directories.

LiveImport tracks modules that either are imported by a registered import statement, or are imported by a tracked module and have a source file in the workspace. A source file is in the workspace if and only if it’s under a workspace directory.

The default workspace is the current working directory when the LiveImport module is imported. Thus, when LiveImport is used in a notebook, the workspace is the directory containing the notebook.

Parameters:

directories – Zero or more path strings or path-like objects. Each path must identify an existing directory.

Raises:

ValueError – One of the specified paths does not exist or exists but is not a directory.

Example: After calling

liveimport.workspace("src", "/opt/notebook-utils")

the workspace is the directory src in the current working directory and the directory /opt/notebook-utils.

If you call

liveimport.workspace()  # No paths given

the workspace is empty, so only modules referenced by registered imports will be tracked.

Note

Changing the workspace does not alter tracking decisions LiveImport has already made. It only affects future decisions. If you want a non-default workspace, its best to change it before registering any imports.

liveimport.hidden_cell_magic(enabled: bool | None = None) None

Configure hidden cell magic.

Parameters:

enabled – Notebook cells that begin with #_%%liveimport run as if they began with %%livemagic if and only if enabled is true. This makes LiveImport cell magic transparent to IDEs like Visual Studio Code, yet still function as desired. Hidden cell magic is enabled by default.

liveimport.auto_sync(enabled: bool | None = None, *, grace: float | None = None, report: bool | None = None) None

Configure automatic sync behavior. By default, automatic syncing is enabled with a grace period of 1.0 seconds and reloads are reported.

Parameters:
  • enabled – LiveImport syncs whenever a notebook cell runs if and only if enabled is true and a grace period since the end of the last cell execution has expired.

  • grace – The minimum time in seconds that must pass between the end of one cell execution and the beginning of the another before LiveImport will sync. The grace period inhibits syncing between cell executions during a multi-cell run, such as running the entire notebook.

  • report – Use Markdown console blocks to report when modules are reloaded by automatic syncing.

class liveimport.ReloadEvent(module: str, reason: str, mtime: float, after: list[str])

Describes a successful reload. Attributes:

module: str

The name of the module reloaded.

reason: str

The reason LiveImport reloaded module, either "modified" or "dependent".

mtime: float

The modification time of the module source file last seen by LiveImport. If reason is "modified", this time changed since LiveImport began tracking or last reloaded module.

after: list[str]

Modules on which module depends which LiveImport has already reloaded as part of the same sync. If reason is "dependent", LiveImport reloaded module solely because it reloaded these modules.

The string representation of a ReloadEvent is an English-language description similar to

Reloaded printmath modified 18 seconds ago

or

Reloaded simulator because printmath reloaded

exception liveimport.ModuleError(module: str, phase: str)

LiveImport has determined there is an issue with the content of a module.

module: str

The name of the module.

phase: str

Phase of processing during which LiveImport detected the erroneous condition, currently either "analysis" or "reload".

__cause__: BaseException

The issue LiveImport encountered. This could be a source error, such as a SyntaxError, or an exception raised while the module is executing during a reload.