Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More

When Lino starts up

Here is what happens when a Lino process wakes up.

The life cycle of a Lino process

site startup

The things that happen at the beginning of a Lino process.

Lino process

A Python process running on a given Lino site. This is either some django-admin command, or a WSGI or ASGI process inside a web server.

There are four major phases in the life of a Lino process:

application definition

The first phase of the site startup when Django settings are being loaded. We see this as a separate phase because Lino does some magics there.

data definition

The second phase of the site startup, when Django loads the database models and does its own startup.

site analysis

The third phase of the site startup, when Django models have been loaded, and Lino analyses them to fill its own data structures.

runtime

When the site startup has finished and the actual process does what it is designed to do.

There are three modules in lino.api named after these phases:

Application definition

The application definition phase:

(1) manage.py sets DJANGO_SETTINGS_MODULE and calls django.core.management.execute_from_command_line(), which loads your settings.py file.

(2) Importing the settings.py module will instantiate your SITE. Here is what happens when the Site class gets instantiated.

(3) Modify Django’s django.utils.log.DEFAULT_LOGGING dict.

(4) Call Site.get_plugin_configs()

(5) Read the lino.ini if it exists.

(6) Call Site.get_plugin_modifiers() and Site.get_installed_plugins() to build the list of plugins.

(7) Import each plugin (just the __init__.py of the package).

(8) Set the INSTALLED_APPS setting and the Site.installed_plugins site attribute. The list of installed plugins is now known and won’t change any more. INSTALLED_APPS is basically the same as Site.installed_plugins, except that the former is a list of module names while the latter is a list of Plugin instances.

(9) Call each plugin’s on_plugins_loaded method.

Note that the above steps happen while the settings.py is still being loaded. This means for example that you cannot access the settings module in your get_plugin_configs or on_plugins_loaded methods. In this phase, everything in lino.api.ad is usable.

Data definition

(10) When Django has finished loading the settings.py file, it starts importing the models.py module of each plugin. We call this the data definition phase. Everything in lino.api.dd is usable during this step. lino.api.rt may be imported but should not be accessed at global module level.

Site startup

(11) When Django has fully populated its models registry (imported all models.py modules), it finds lino.AppConfig and runs its ready() method, which does nothing more and nothing less than run Site.startup(). This kicks off the site analysis phase. Which does the following:

(12) Instantiate the kernel. settings.SITE.kernel is now an instance of lino.core.kernel.Kernel instead of None.

(13) Fill Site.models, an attrdict mapping the app_label of each installed plugin to their curresponding models.py module.

(14) Emit the lino.core.signals.pre_startup signal.

(15) Run pre_site_startup of each plugin.

(16) Run Kernel.kernel_startup(), which does what’s explained in Kernel startup below.

(17) Run Site.do_site_startup

(18) Run lino.core.plugins.Plugin.post_site_startup() on each plugin

(19) Emit the lino.core.signals.post_startup signal

Kernel startup

(20) Register Site.shutdown() to atexit and stop signal handler.

(21) Install a DisableDeleteHandler for each model into Model._lino_ddh.

(22) Install lino.core.model.Model attributes and methods into raw Django Models that don’t inherit from it.

(23) Populate Site.GFK_LIST, a list of all generic foreign key fields in the database.

(24) Import Site.user_types_module

(25) Analyze ForeignKeys and populate the DisableDeleteHandler.

(26) Import Site.workflows_module

(27) Run lino.core.plugins.Plugin.before_analyze() on each plugin

(28) Emit the lino.core.signals.pre_analyze signal

(29) Run lino.core.site.Site.setup_actions()

(30) Import Site.custom_layouts_module if defined.

(31) Call lino.core.model.Model.on_analyze() on every model.

(32) Call lino.core.model.Model.collect_virtual_fields() on every model. This attaches virtual fields to the model that declares them.

(33) Run lino.core.plugins.Plugin.before_actors_discover() on each plugin.

(34) Discover and initialize actors

(35) Emit the lino.core.signals.post_analyze signal

(36) Run lino.core.actors.Actor.after_site_setup() on each actor

(37) Emit the lino.core.signals.pre_ui_build signal

(38) Run lino.core.plugins.Plugin.on_ui_init() on each plugin

Runtime

(39) When site startup has finished, we finally enter the runtime phase. Only now everything in lino.api.rt is usable.