Welcome | Get started | Dive into Lino | Contribute | Topics | Reference | More


This is the 2023 change log for Lino. Learn how to read and maintain this document in Documenting changes.


Changes in database schema for Lino Noi:

  • new field Ticket.team will be filled by pm checkdata -f

  • fields Site.company and Site.contact_person have been removed.


We removed the dash of the --keep-media and --remove-media options of pm prep --keepmedia and pm initdb --removemedia


New feature #5288 (table of contents of a content page). Added a new memo command [toc], whicih is allowed only in the body of a content page. Internal API change: lino.modlib.memo.parser.MemoParser.parse() has a new optional argument 'context'. Until now there was no way to let a memo command handler know the database row it is running on. The lino.modlib.memo.Previewable mixin uses this and defines a keyword self into the context. As a side effect, lino.modlib.uploads.Upload now implements lino.modlib.publisher.Publishable.

Fixed #4084 (Comment.owner is empty when replying to a comment). Also added a data checker that fixes existing data.


Fixed #5278 (send_pending_emails_often caused a SynchronousOnlyOperation exception)


Replace lino_runworker by linod in your /etc/supervisor/conf.d/*.conf files.


Removed the option --nobuildcache from pm initdb (and pm prep) because initdb no longer calls pm buildcache at all. You might have to change the following line in your restore.py file:

call_command('initdb', interactive=args.interactive, buildcache=False)


call_command('initdb', interactive=args.interactive)


The short preview of a comment, page or blog entry now contains at most one image, and this image has a fixed size.

New plugin setting memo.short_preview_image_height.


#5191 : The restore.py script no longer calls pm buildcache. New option --nobuildcache for pm initdb.


#5172 : A series of changes in lino.modlib.linod : a single model linod.BackgroundTask instead of JobRule and Job. In your restore.py uncomment the following lines:

# execfile("linod_jobrule.py", *args)
# execfile("linod_job.py", *args)

Update your supervisor config files: The django-admin command lino_runworker has been renamed to linod.

#4962 : Lino can now do weekly summaries. See lino.modlib.summaries.


pm initdb can now remove the media directory when option --remove-media is specified. This is used by pm prep.


Add setting cal.calendar_fieldnames Remove lino_xl.lib.cal.Event.get_calendar (or mark private. See next line) Add Event._get_calendar.


Fixed a bug in calview.DailyPlannerRow.get_plannable_entries() that caused the AM planner row to also show the PM calendar entries when both start_time and end_time were non-empty. The commit is evident.


The lino.modlib.memo.truncate_comment() function has been reimplemented and doctests are now in a separate document: Truncating HTML texts.


api.doctst.get_json_soup() now supports URIs that return a delayed_value in React.


Remove collectstatic command (extended). Add buildcache command.

What collectstatic had done so far is now saperated into the following three commands:

  1. collectstatic

  2. makehelp

  3. buildcache


Some optimizations in lino_xl.lib.calview. See https://luc.lino-framework.org/blog/2023/0502.html


Removed columns cal.Event.access_class and cal.Event.sequence. Removed choicelist cal.AccessClass In lino_xl.lib.cal, renamed plugin configuration parameter demo_absences to with_demo_absences.


More changes for #4935 (bug with picture format in [upload] memo command). Added 6 demo photos by Luc Saffre. More documentation. New memo command [gallery]. The cms1 demo project now includes a page with usage examples of the [upload] and [gallery] commands.


Fixed a bug: The [upload] memo command did not parse format specifiers correctly.


Added feature "multiple web front ends". The Site.default_ui attribute is now deprecated but currently still yields the old behaviour. The work is not finished, but already now in cms1 we have publisher as "root" front end and react as the "admin" front end:

web_front_ends = [
  (None, "lino.modlib.publisher"),
  ('admin', "lino_react.react")]


Refactor: moved RecurrenceSet, Recurrences, DurationUnit, DurationUnits & Weekdays from lino_xl.lib.cal to lino.modlib.system.

Refactor: moved Procedure, Procedures, Job, JobRule, Tasks & SetupTasks from lino.modlib.system to lino.modlib.linod

Added the following classes to linod plugin: lino.modlib.linod.RunJob lino.modlib.linod.LogLevels lino.modlib.linod.JobsByRule

A linod.Job is not editable and is only a historical record of a system task.

Refactor: moved Job.cancelled to JobRule

Added JobRule.log_level.


A series of optimizations in lino_xl.lib.pages for #4872 (Generated content in pages.Node): Nodes with "dynamic" or "generated" content, e.g. the latest blog entries, now have two different ways of generating their content: either as a single paragraph or as a story. Node now has an insert dialog.


Added the following classes to system plugin: lino.modlib.linod.Procedure lino.modlib.linod.Procedures lino.modlib.linod.JobRule lino.modlib.linod.JobRules lino.modlib.linod.Job lino.modlib.linod.Jobs lino.modlib.linod.tasks.Tasks lino.modlib.linod.SetupTasks and removed dependencies to schedule python package.

Add ChoiceListField.strict attribute.


Ticket #4742 (Make the CMS demo more convincing). Visible result is the cms1 demo project. This caused a series of changes: In lino_xl.lib.pages we renamed Page to Node. lino_xl.lib.pages.Node now uses Babel fields instead of separate database rows for each language. Internal optimizations and bugfixes in lino.modlib.publisher and the core (action requests). New plugin setting memo.short_preview_length. The experimental UploadVCardFile model exists now only when contacts.use_vcard_export is True. The ShowAsHtml action was defined four times.


The docs produced by makehelp made Sphinx warn about "Title overline too short" or "Malformed" table when awide unicode char was being used. Now rstgen uses docutils.utils.column_width() when generating headers and tables.


The synodal package now knows our public demo servers. We added some usage examples in the README.rst, and this file is no longer being generated by inv bd. And it is now being tested by inv test.


Fixed #4864 (AttributeError: 'Site' object has no attribute 'obj2memo'), which caused a little avalanche of internal optimizations. For example, lino.utils.DelayedValue() is now a function that directly returns a dict rather than instantiating an object that has no other purpose than being converted to a dict by lino.utils.py2js(). Also Layout.get_layout_handle no longer takes an argument to specify the front end (because it was always the same).

As a side effect, in lino_welfare.modlib.cv the three system.SiteConfig fields propgroup_skills, propgroup_softskills and propgroup_obstacles have been replaced by a field PropGroup.property_area, which points to a choice in new choicelist PropertyAreas. Until now lino_xl.lib.properties was considered deprecated (and as a consequence the lino_welcht.modlib.cv defines three hard-coded database models Skill, SoftSkill and Obstacle), but this change might save the plugin from getting deprecated. To be observed. Data migration: (1) edit the restore.py file to remove propgroup_skills, propgroup_softskills and propgroup_obstacles, (2) set the PropGroup.property_area field for the three property groups "Skills", "Softskills" and "Obstacles".


Fixed #4864, which caused disturbing regressions on two production sites.

Release to pypi: Lino, XL, Noi


The demo date in your settings.py file (the_demo_date) can now be specified as a str or int, i.e. without having to import datetime. In that case Lino will convert it during startup to a datetime.date using rstgen.utils.i2d().


Renamed obj2str() to lino.core.requests.BaseRequest.obj2htmls(). The s stands for "safe". It seems that we will move away from using etree and use Django's mark_safe system instead.


settings.SITE.build_site_cache now accepts a new keyword argument later. This simply touches the settings.py. Used in after_ui.save() of lino_xl.lib.excerpts.ExcerptType.


Done #4801 (Insert images into arbitrary places using memo commands). Details see Luc's blog. Data migration: in your restore.py uncomment the line that loads comments_mention.py. The lino.modlib.memo.Mention objects will be created by pm checkdata -f.


The lino_xl.lib.working plugin now supports sub-sessions: when a user works on two tickets at the same time (has two sessions open), and when one of them encompasses the other, then the encompassing session automatically subtracts the duration of the sub-session. New database field Session.computed_duration

invoicing.Item now has a meaningful allow_cascaded_delete.


New option --simulate for the pm dump2py command.

Fixed #4780. A site maintainer can now switch the front end without changing the database structure. Plugins can now deactivate themselves. The lino.core.plugin.Plugin class has two new methods deactivate() and is_active(). When a plugin is inactive, its database models exist but otherwise almost everything, including its actors, becomes non-existent. The tinymce and extensible plugins now deactivate themselves in their on_init() method when the default_ui is not extjs.