lino 25.5.0__py3-none-any.whl → 25.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lino/__init__.py +1 -1
- lino/core/actions.py +2 -8
- lino/core/actors.py +5 -3
- lino/core/choicelists.py +8 -11
- lino/core/dbtables.py +7 -7
- lino/core/elems.py +6 -0
- lino/core/fields.py +30 -4
- lino/core/kernel.py +6 -0
- lino/core/model.py +0 -7
- lino/core/store.py +4 -5
- lino/core/tables.py +6 -8
- lino/help_texts.py +3 -1
- lino/mixins/duplicable.py +9 -3
- lino/mixins/ref.py +9 -0
- lino/mixins/registrable.py +2 -2
- lino/mixins/sequenced.py +12 -8
- lino/modlib/extjs/ext_renderer.py +1 -1
- lino/modlib/gfks/fields.py +1 -1
- lino/modlib/jinja/renderer.py +1 -0
- lino/modlib/linod/models.py +1 -1
- lino/modlib/periods/fixtures/std.py +1 -3
- lino/modlib/periods/models.py +26 -5
- lino/modlib/weasyprint/__init__.py +1 -0
- lino/modlib/weasyprint/choicelists.py +2 -11
- lino/modlib/weasyprint/config/weasyprint/base.weasy.html +1 -1
- lino/utils/__init__.py +20 -0
- lino/utils/choosers.py +21 -15
- {lino-25.5.0.dist-info → lino-25.5.1.dist-info}/METADATA +1 -1
- {lino-25.5.0.dist-info → lino-25.5.1.dist-info}/RECORD +32 -32
- {lino-25.5.0.dist-info → lino-25.5.1.dist-info}/WHEEL +0 -0
- {lino-25.5.0.dist-info → lino-25.5.1.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.5.0.dist-info → lino-25.5.1.dist-info}/licenses/COPYING +0 -0
lino/__init__.py
CHANGED
@@ -31,7 +31,7 @@ from django import VERSION
|
|
31
31
|
from django.apps import AppConfig
|
32
32
|
from django.conf import settings
|
33
33
|
import warnings
|
34
|
-
__version__ = '25.5.
|
34
|
+
__version__ = '25.5.1'
|
35
35
|
|
36
36
|
# import setuptools # avoid UserWarning "Distutils was imported before Setuptools"?
|
37
37
|
|
lino/core/actions.py
CHANGED
@@ -31,18 +31,12 @@ from django.core.exceptions import BadRequest
|
|
31
31
|
|
32
32
|
from django.apps import apps
|
33
33
|
|
34
|
-
get_models = apps.get_models
|
35
|
-
|
36
34
|
|
37
35
|
def discover_choosers():
|
38
36
|
logger.debug("Discovering choosers for database fields...")
|
39
|
-
|
40
|
-
|
41
|
-
# ~ n = 0
|
42
|
-
allfields = model._meta.fields
|
43
|
-
for field in allfields:
|
37
|
+
for model in apps.get_models():
|
38
|
+
for field in model._meta.fields:
|
44
39
|
check_for_chooser(model, field)
|
45
|
-
# ~ logger.debug("Discovered %d choosers in model %s.",n,model)
|
46
40
|
|
47
41
|
|
48
42
|
def resolve_layout(cls, k, spec, layout_class, **options):
|
lino/core/actors.py
CHANGED
@@ -17,10 +17,8 @@ from django.db import models
|
|
17
17
|
from django.conf import settings
|
18
18
|
from django.utils.translation import gettext_lazy as _
|
19
19
|
from django.utils.html import format_html, mark_safe, SafeString
|
20
|
-
from django.core.exceptions import BadRequest
|
21
20
|
|
22
21
|
from lino import logger
|
23
|
-
from lino.utils import isiterable
|
24
22
|
from lino.utils import MissingRow
|
25
23
|
from lino.core import fields
|
26
24
|
from lino.core import actions
|
@@ -532,7 +530,11 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
532
530
|
@classmethod
|
533
531
|
def get_chooser_for_field(cls, fieldname):
|
534
532
|
d = getattr(cls, "_choosers_dict", {})
|
535
|
-
|
533
|
+
ch = d.get(fieldname, None)
|
534
|
+
if ch is not None:
|
535
|
+
return ch
|
536
|
+
if cls.model is not None:
|
537
|
+
return cls.model.get_chooser_for_field(fieldname)
|
536
538
|
|
537
539
|
# @classmethod
|
538
540
|
# def inject_field(cls, name, fld):
|
lino/core/choicelists.py
CHANGED
@@ -1,25 +1,19 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2008-
|
2
|
+
# Copyright 2008-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
"""
|
5
5
|
Defines the classes :class:`Choice` and :class:`ChoiceList`. See
|
6
6
|
:doc:`/dev/choicelists`.
|
7
7
|
"""
|
8
8
|
|
9
|
-
from future.utils import with_metaclass
|
10
|
-
|
11
9
|
import warnings
|
12
|
-
|
13
10
|
from django.utils.translation import gettext_lazy as _
|
14
11
|
from django.utils.functional import lazy
|
15
|
-
|
16
12
|
# from django.utils.deconstruct import deconstructible
|
17
13
|
from django.db import models
|
18
14
|
from django.conf import settings
|
19
|
-
from django.db.models import NOT_PROVIDED
|
20
15
|
from django.db.migrations.serializer import BaseSerializer
|
21
16
|
from django.db.migrations.writer import MigrationWriter
|
22
|
-
|
23
17
|
from lino.utils import MissingRow
|
24
18
|
from lino.core.utils import resolve_field
|
25
19
|
from lino.core import actions
|
@@ -33,8 +27,9 @@ STRICT = True
|
|
33
27
|
VALUE_FIELD = models.CharField(_("value"), max_length=20)
|
34
28
|
VALUE_FIELD.attname = "value"
|
35
29
|
|
36
|
-
|
37
30
|
# @deconstructible
|
31
|
+
|
32
|
+
|
38
33
|
class Choice(fields.TableRow):
|
39
34
|
"""
|
40
35
|
A constant value whose string representation depends on the current language
|
@@ -345,7 +340,7 @@ class PointingChoice(Choice):
|
|
345
340
|
return not isinstance(self.get_object(severe=False), MissingRow)
|
346
341
|
|
347
342
|
|
348
|
-
class ChoiceList(
|
343
|
+
class ChoiceList(tables.AbstractTable, metaclass=ChoiceListMeta):
|
349
344
|
"""
|
350
345
|
User-defined choice lists must inherit from this base class.
|
351
346
|
|
@@ -743,12 +738,14 @@ class ChoiceList(with_metaclass(ChoiceListMeta, tables.AbstractTable)):
|
|
743
738
|
|
744
739
|
Override this to customize the display text of choices.
|
745
740
|
|
741
|
+
Usage example: :class:`lino.modlib.system.DisplayColors`.
|
742
|
+
|
746
743
|
:class:`lino.modlib.users.UserGroups` and
|
747
744
|
:class:`lino.modlib.cv.models.CefLevel` used to do this before
|
748
745
|
we had the :attr:`ChoiceList.show_values` option.
|
749
746
|
|
750
|
-
|
751
|
-
|
747
|
+
The return value must be lazily translatable because it is also used to
|
748
|
+
build the `choices` attribute of ChoiceListFields on this choicelist.
|
752
749
|
|
753
750
|
Note that Django's `lazy` function has a list of "resultclasses" that
|
754
751
|
are used "so that the automatic forcing of the lazy evaluation code is
|
lino/core/dbtables.py
CHANGED
@@ -228,13 +228,13 @@ class Table(AbstractTable):
|
|
228
228
|
return qs.model.objects.none()
|
229
229
|
return qs.filter(flt)
|
230
230
|
|
231
|
-
@classmethod
|
232
|
-
def get_chooser_for_field(self, fieldname):
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
231
|
+
# @classmethod
|
232
|
+
# def get_chooser_for_field(self, fieldname):
|
233
|
+
# ch = super().get_chooser_for_field(fieldname)
|
234
|
+
# if ch is not None:
|
235
|
+
# return ch
|
236
|
+
# if self.model is not None:
|
237
|
+
# return self.model.get_chooser_for_field(fieldname)
|
238
238
|
|
239
239
|
@classmethod
|
240
240
|
def column_choices(self):
|
lino/core/elems.py
CHANGED
@@ -61,6 +61,7 @@ from lino.core import tables
|
|
61
61
|
from lino.core.gfks import GenericForeignKey
|
62
62
|
from lino.utils.format_date import fds
|
63
63
|
from lino.modlib.users.utils import get_user_profile
|
64
|
+
from lino.modlib.gfks.fields import GenericForeignKeyIdField
|
64
65
|
|
65
66
|
# from etgen import etree
|
66
67
|
from etgen.html2rst import html2rst
|
@@ -2550,6 +2551,7 @@ class TabPanel(Panel):
|
|
2550
2551
|
|
2551
2552
|
_FIELD2ELEM = [
|
2552
2553
|
# (dd.Constant, ConstantElement),
|
2554
|
+
(GenericForeignKeyIdField, ComplexRemoteComboFieldElement),
|
2553
2555
|
(fields.RecurrenceField, RecurrenceElement),
|
2554
2556
|
(fields.DelayedHtmlBox, DisplayElement),
|
2555
2557
|
(fields.HtmlBox, HtmlBoxElement),
|
@@ -2605,6 +2607,9 @@ def field2elem(layout_handle, field, **kw):
|
|
2605
2607
|
holder = layout_handle.layout.get_chooser_holder()
|
2606
2608
|
ch = holder.get_chooser_for_field(field.name)
|
2607
2609
|
|
2610
|
+
# if field.name == "answer":
|
2611
|
+
# print(f"20250511 {field} {ch} {field.choices}")
|
2612
|
+
|
2608
2613
|
if ch:
|
2609
2614
|
kw.update(can_create_choice=ch.can_create_choice)
|
2610
2615
|
if ch.can_create_choice or not ch.force_selection:
|
@@ -2619,6 +2624,7 @@ def field2elem(layout_handle, field, **kw):
|
|
2619
2624
|
return ForeignKeyElement(layout_handle, field, **kw)
|
2620
2625
|
else:
|
2621
2626
|
return ComplexRemoteComboFieldElement(layout_handle, field, **kw)
|
2627
|
+
|
2622
2628
|
if field.choices:
|
2623
2629
|
if isinstance(field, choicelists.ChoiceListField):
|
2624
2630
|
if field.choicelist.preferred_width is None:
|
lino/core/fields.py
CHANGED
@@ -8,7 +8,6 @@ related to fields.
|
|
8
8
|
|
9
9
|
#fmt: off
|
10
10
|
|
11
|
-
from lino import logger
|
12
11
|
import datetime
|
13
12
|
from decimal import Decimal
|
14
13
|
|
@@ -22,6 +21,7 @@ from django.core.exceptions import FieldDoesNotExist
|
|
22
21
|
from django.db.models.fields import NOT_PROVIDED
|
23
22
|
from django.utils.functional import cached_property
|
24
23
|
|
24
|
+
from lino import logger
|
25
25
|
from lino.utils.html import E, forcetext, tostring, SafeString, escape, mark_safe
|
26
26
|
|
27
27
|
from lino.core.utils import (
|
@@ -38,8 +38,8 @@ from lino.utils import isiterable
|
|
38
38
|
from lino.utils import get_class_attr
|
39
39
|
from lino.utils import IncompleteDate
|
40
40
|
from lino.utils import quantities
|
41
|
-
from lino.utils import choosers
|
42
41
|
from lino.utils.quantities import Duration
|
42
|
+
from lino.modlib.gfks.fields import GenericForeignKeyIdField
|
43
43
|
|
44
44
|
from .signals import pre_ui_save
|
45
45
|
|
@@ -543,7 +543,7 @@ VFIELD_ATTRIBS = frozenset(
|
|
543
543
|
"""to_python choices save_form_data
|
544
544
|
value_to_string max_length remote_field
|
545
545
|
max_digits verbose_name decimal_places wildcard_data_elem
|
546
|
-
blank""".split()
|
546
|
+
blank choices""".split()
|
547
547
|
)
|
548
548
|
|
549
549
|
|
@@ -618,6 +618,7 @@ class VirtualField(FakeField):
|
|
618
618
|
"Invalid return type spec {} for {} : {}".format(
|
619
619
|
f, self, e)
|
620
620
|
)
|
621
|
+
self.field = f
|
621
622
|
|
622
623
|
if isinstance(f, FakeField):
|
623
624
|
# sortable_by = f.sortable_by
|
@@ -628,6 +629,11 @@ class VirtualField(FakeField):
|
|
628
629
|
# if sortable_by and isinstance(sortable_by, list):
|
629
630
|
# sortable_by = sortable_by[0]
|
630
631
|
|
632
|
+
# if isinstance(f, VirtualField):
|
633
|
+
# delegate = f.return_type
|
634
|
+
# else:
|
635
|
+
# delegate = f
|
636
|
+
|
631
637
|
if isinstance(f, models.ForeignKey):
|
632
638
|
f.remote_field.model = resolve_model(f.remote_field.model)
|
633
639
|
set_default_verbose_name(f)
|
@@ -1147,6 +1153,7 @@ class DummyField(FakeField):
|
|
1147
1153
|
|
1148
1154
|
# choices = []
|
1149
1155
|
# primary_key = False
|
1156
|
+
field = None # Used e.g. to test whether it's a dummy field
|
1150
1157
|
|
1151
1158
|
def __init__(self, dummy_value=None):
|
1152
1159
|
super().__init__()
|
@@ -1266,6 +1273,13 @@ class TableRow(object):
|
|
1266
1273
|
|
1267
1274
|
"""
|
1268
1275
|
|
1276
|
+
@classmethod
|
1277
|
+
def get_chooser_for_field(cls, fieldname):
|
1278
|
+
d = getattr(cls, "_choosers_dict", {})
|
1279
|
+
# if fieldname.endswith("__municipality"):
|
1280
|
+
# print("20200425 Model.get_chooser_for_field", cls, fieldname, d)
|
1281
|
+
return d.get(fieldname, None)
|
1282
|
+
|
1269
1283
|
@classmethod
|
1270
1284
|
def setup_parameters(cls, params):
|
1271
1285
|
"""Inheritable hook for defining parameters for every actor on this model.
|
@@ -1597,6 +1611,7 @@ def pointer_factory(cls, othermodel, *args, **kw):
|
|
1597
1611
|
|
1598
1612
|
|
1599
1613
|
def make_remote_field(model, name):
|
1614
|
+
from lino.utils import choosers
|
1600
1615
|
parts = name.split("__")
|
1601
1616
|
if len(parts) == 1:
|
1602
1617
|
return
|
@@ -1815,7 +1830,6 @@ def choices_for_field(ar, holder, field):
|
|
1815
1830
|
t = m.get_default_table()
|
1816
1831
|
# qs = t.create_request(request=ar.request).data_iterator
|
1817
1832
|
qs = t.create_request(parent=ar).data_iterator
|
1818
|
-
|
1819
1833
|
# logger.info('20120710 choices_view(FK) %s --> %s', t, qs.query)
|
1820
1834
|
|
1821
1835
|
def row2dict(obj, d):
|
@@ -1823,6 +1837,18 @@ def choices_for_field(ar, holder, field):
|
|
1823
1837
|
obj, ar, field)
|
1824
1838
|
d[constants.CHOICES_VALUE_FIELD] = obj.pk
|
1825
1839
|
return d
|
1840
|
+
# elif isinstance(field, GenericForeignKeyIdField):
|
1841
|
+
# ct = getattr(ar.selected_rows[0], field.type_field)
|
1842
|
+
# m = ct.model_class()
|
1843
|
+
# # print(f"20250511 {field.remote_field} {repr(field.type_field)}")
|
1844
|
+
# t = m.get_default_table()
|
1845
|
+
# qs = t.create_request(parent=ar).data_iterator
|
1846
|
+
#
|
1847
|
+
# def row2dict(obj, d):
|
1848
|
+
# d[constants.CHOICES_TEXT_FIELD] = holder.get_choices_text(
|
1849
|
+
# obj, ar, field)
|
1850
|
+
# d[constants.CHOICES_VALUE_FIELD] = obj.pk
|
1851
|
+
# return d
|
1826
1852
|
else:
|
1827
1853
|
raise http.Http404("No choices for %s" % field)
|
1828
1854
|
return (qs, row2dict)
|
lino/core/kernel.py
CHANGED
@@ -44,6 +44,7 @@ from django.db import models
|
|
44
44
|
# import lino # for is_testing
|
45
45
|
from lino import logger
|
46
46
|
from lino.utils import codetime
|
47
|
+
from lino.utils.choosers import check_for_chooser
|
47
48
|
from lino.utils.html import E
|
48
49
|
# from lino.core.utils import format_request
|
49
50
|
# from lino.utils import isiterable
|
@@ -470,6 +471,11 @@ class Kernel(object):
|
|
470
471
|
# ~ choosers.discover()
|
471
472
|
actions.discover_choosers()
|
472
473
|
|
474
|
+
for a in actors.actors_list:
|
475
|
+
for name, field in a.virtual_fields.items():
|
476
|
+
assert name == field.name
|
477
|
+
check_for_chooser(a, field)
|
478
|
+
|
473
479
|
for a in actors.actors_list:
|
474
480
|
a.on_analyze(site)
|
475
481
|
|
lino/core/model.py
CHANGED
@@ -726,13 +726,6 @@ class Model(models.Model, fields.TableRow):
|
|
726
726
|
# return self.preview(ar)
|
727
727
|
# #~ username = kw.pop('username',None)
|
728
728
|
|
729
|
-
@classmethod
|
730
|
-
def get_chooser_for_field(cls, fieldname):
|
731
|
-
d = getattr(cls, "_choosers_dict", {})
|
732
|
-
# if fieldname.endswith("__municipality"):
|
733
|
-
# print("20200425 Model.get_chooser_for_field", cls, fieldname, d)
|
734
|
-
return d.get(fieldname, None)
|
735
|
-
|
736
729
|
def get_printable_target_stem(self):
|
737
730
|
return self._meta.app_label + "." + self.__class__.__name__ + "-" + str(self.pk)
|
738
731
|
|
lino/core/store.py
CHANGED
@@ -647,13 +647,12 @@ class RowClassStoreField(SpecialStoreField):
|
|
647
647
|
name = "row_class"
|
648
648
|
|
649
649
|
def full_value_from_object(self, obj, ar=None):
|
650
|
-
|
651
|
-
|
652
|
-
ar.renderer.row_classes_map.get(s, "")
|
650
|
+
lst = [
|
651
|
+
ar.renderer.row_classes_map.get(s, s)
|
653
652
|
for s in self.store.actor.get_row_classes(obj, ar)
|
654
653
|
]
|
655
|
-
)
|
656
|
-
|
654
|
+
# print(f"20250509x {obj} -> {lst}")
|
655
|
+
return " ".join(lst)
|
657
656
|
|
658
657
|
|
659
658
|
class DisableEditingStoreField(SpecialStoreField):
|
lino/core/tables.py
CHANGED
@@ -566,16 +566,14 @@ method in order to sort the rows of the queryset.
|
|
566
566
|
For example, if you have two models :class:`Book` and :class:`Author`,
|
567
567
|
and a foreign key :attr:`Book.author`, which points to the author of the
|
568
568
|
book, and a table `BooksByAuthor` having `master_key` set to
|
569
|
-
``'author'``, then
|
570
|
-
<PK>}` where `<PK>` is the primary key of the action
|
571
|
-
:attr:`master_instance
|
569
|
+
``'author'``, then :meth:`BooksByAuthor.get_filter_kw` would return a
|
570
|
+
dict `{'author': <PK>}` where `<PK>` is the primary key of the action
|
571
|
+
request's :attr:`master_instance
|
572
572
|
<lino.core.requests.BaseRequest.master_instance>`.
|
573
573
|
|
574
|
-
Another example is
|
575
|
-
|
576
|
-
|
577
|
-
detail of a session we want to display a table of related blog
|
578
|
-
entries.
|
574
|
+
Another example is :class:`lino_xl.lib.tickets.EntriesBySession`, where
|
575
|
+
blog entries are not directly linked to a session, but in the detail of
|
576
|
+
a session we want to display a table of related blog entries.
|
579
577
|
|
580
578
|
:class:`lino_xl.lib.households.SiblingsByPerson` Household
|
581
579
|
members are not directly linked to a Person, but usually a
|
lino/help_texts.py
CHANGED
@@ -32,7 +32,7 @@ help_texts = {
|
|
32
32
|
'lino.mixins.dupable.SimilarObjects' : _("""Shows the other objects that are similar to this one."""),
|
33
33
|
'lino.mixins.duplicable.Duplicate' : _("""Duplicate the selected row."""),
|
34
34
|
'lino.mixins.duplicable.Duplicate.run_from_ui' : _("""This actually runs the action."""),
|
35
|
-
'lino.mixins.duplicable.Duplicable' : _("""Adds a row action “Duplicate
|
35
|
+
'lino.mixins.duplicable.Duplicable' : _("""Adds a row action “Duplicate”, which duplicates (creates a clone of) the object it was called on."""),
|
36
36
|
'lino.mixins.human.Human' : _("""Base class for models that represent a human."""),
|
37
37
|
'lino.mixins.human.Human.title' : _("""Used to specify a professional position or academic qualification like “Dr.” or “PhD”."""),
|
38
38
|
'lino.mixins.human.Human.first_name' : _("""The first name, also known as given name."""),
|
@@ -70,6 +70,7 @@ help_texts = {
|
|
70
70
|
'lino.mixins.ref.Referrable.ref' : _("""The reference. This must be either empty or unique."""),
|
71
71
|
'lino.mixins.ref.Referrable.ref_max_length' : _("""The preferred width of the ref field."""),
|
72
72
|
'lino.mixins.ref.Referrable.on_duplicate' : _("""Before saving a duplicated object for the first time, we must change the ref in order to avoid an IntegrityError."""),
|
73
|
+
'lino.mixins.ref.Referrable.get_next_row' : _("""Return the next database row, or None if this is the last one."""),
|
73
74
|
'lino.mixins.ref.Referrable.get_by_ref' : _("""Return the object identified by the given reference."""),
|
74
75
|
'lino.mixins.ref.Referrable.quick_search_filter' : _("""Overrides the default behaviour defined in lino.core.model.Model.quick_search_filter(). For Referrable objects, when quick-searching for a text containing only digits, the user usually means the ref and not the primary key."""),
|
75
76
|
'lino.mixins.ref.StructuredReferrable' : _("""A referrable whose ref field is used to define a hierarchical structure."""),
|
@@ -97,6 +98,7 @@ help_texts = {
|
|
97
98
|
'lino.mixins.sequenced.Sequenced.get_siblings' : _("""Return a Django Queryset with all siblings of this, or None if this is a root element which cannot have any siblings."""),
|
98
99
|
'lino.mixins.sequenced.Sequenced.set_seqno' : _("""Initialize seqno to the seqno of eldest sibling + 1."""),
|
99
100
|
'lino.mixins.sequenced.Sequenced.seqno_changed' : _("""If the user manually assigns a seqno."""),
|
101
|
+
'lino.mixins.sequenced.Sequenced.dndreorder' : _("""A place holder column for drag and drop row reorder on React front end"""),
|
100
102
|
'lino.mixins.sequenced.Hierarchical' : _("""Model mixin for things that have a “parent” and “siblings”."""),
|
101
103
|
'lino.mixins.sequenced.Hierarchical.children_summary' : _("""A comma-separated list of the children."""),
|
102
104
|
'lino.mixins.sequenced.Hierarchical.get_parental_line' : _("""Return an ordered list of all ancestors of this instance."""),
|
lino/mixins/duplicable.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2012-
|
2
|
+
# Copyright 2012-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
"""Defines the model mixin :class:`Duplicable`. "duplicable"
|
5
5
|
[du'plikəblə] means "able to produce a duplicate
|
@@ -9,10 +9,11 @@
|
|
9
9
|
|
10
10
|
from django.utils.translation import gettext_lazy as _
|
11
11
|
|
12
|
+
from lino import logger
|
12
13
|
from lino.core import actions
|
13
14
|
from lino.core import model
|
14
15
|
from lino.core.diff import ChangeWatcher
|
15
|
-
from lino.core.roles import Expert
|
16
|
+
# from lino.core.roles import Expert
|
16
17
|
|
17
18
|
|
18
19
|
class Duplicate(actions.Action):
|
@@ -73,6 +74,7 @@ class Duplicate(actions.Action):
|
|
73
74
|
new.full_clean()
|
74
75
|
new.save(force_insert=True)
|
75
76
|
cw = ChangeWatcher(new)
|
77
|
+
relcount = 0
|
76
78
|
|
77
79
|
for fk, qs in related:
|
78
80
|
for relobj in qs:
|
@@ -80,6 +82,7 @@ class Duplicate(actions.Action):
|
|
80
82
|
setattr(relobj, fk.name, new)
|
81
83
|
relobj.on_duplicate(ar, new)
|
82
84
|
relobj.save(force_insert=True)
|
85
|
+
relcount += 1
|
83
86
|
|
84
87
|
new.after_duplicate(ar, obj)
|
85
88
|
|
@@ -87,6 +90,9 @@ class Duplicate(actions.Action):
|
|
87
90
|
new.full_clean()
|
88
91
|
new.save()
|
89
92
|
|
93
|
+
logger.info("%s has been duplicated to %s (%d related rows)",
|
94
|
+
obj, new, relcount)
|
95
|
+
|
90
96
|
return new
|
91
97
|
|
92
98
|
def run_from_ui(self, ar, **kw):
|
@@ -115,7 +121,7 @@ class Duplicate(actions.Action):
|
|
115
121
|
|
116
122
|
|
117
123
|
class Duplicable(model.Model):
|
118
|
-
"""Adds a row action "Duplicate" which duplicates (creates a clone
|
124
|
+
"""Adds a row action "Duplicate", which duplicates (creates a clone
|
119
125
|
of) the object it was called on.
|
120
126
|
|
121
127
|
Subclasses may override :meth:`lino.core.model.Model.on_duplicate`
|
lino/mixins/ref.py
CHANGED
@@ -10,6 +10,7 @@ from django.utils.translation import gettext_lazy as _
|
|
10
10
|
from django.db.models.functions import Length
|
11
11
|
|
12
12
|
from lino.utils.html import E
|
13
|
+
from lino.utils import nextref
|
13
14
|
from lino.core import model
|
14
15
|
from lino.core.fields import displayfield
|
15
16
|
|
@@ -61,6 +62,14 @@ class Referrable(model.Model):
|
|
61
62
|
def __str__(self):
|
62
63
|
return self.ref or super().__str__()
|
63
64
|
|
65
|
+
def get_next_row(self):
|
66
|
+
"""Return the next database row, or None if this is the last one.
|
67
|
+
"""
|
68
|
+
ref = nextref(self.ref)
|
69
|
+
if ref is None:
|
70
|
+
return None
|
71
|
+
return self.__class__.get_by_ref(ref, None)
|
72
|
+
|
64
73
|
@staticmethod
|
65
74
|
def ref_prefix(obj, ar=None):
|
66
75
|
return obj.as_ref_prefix(ar)
|
lino/mixins/registrable.py
CHANGED
@@ -37,7 +37,7 @@ class Registrable(model.Model):
|
|
37
37
|
Base class to anything that may be "registered" and "deregistered", where
|
38
38
|
"registered" means "this object has been taken account of".
|
39
39
|
|
40
|
-
For example, when a :term:`
|
40
|
+
For example, when a :term:`numbered voucher` is registered, its associated
|
41
41
|
:term:`ledger movements <ledger movement>` have been generated.
|
42
42
|
Deregistering a voucher will first delete these movements.
|
43
43
|
|
@@ -45,7 +45,7 @@ class Registrable(model.Model):
|
|
45
45
|
usually limited to certain fields.
|
46
46
|
|
47
47
|
:class:`lino_xl.lib.cal.Reservation` is an example of a registrable that is
|
48
|
-
not a
|
48
|
+
not a numbered voucher.
|
49
49
|
|
50
50
|
Subclasses must themselves define a field :attr:`state`.
|
51
51
|
|
lino/mixins/sequenced.py
CHANGED
@@ -279,15 +279,11 @@ class Sequenced(Duplicable):
|
|
279
279
|
Initialize `seqno` to the `seqno` of eldest sibling + 1.
|
280
280
|
"""
|
281
281
|
qs = self.get_siblings().order_by("seqno")
|
282
|
-
if qs
|
283
|
-
self.seqno =
|
282
|
+
if (count := qs.count()) == 0:
|
283
|
+
self.seqno = 1
|
284
284
|
else:
|
285
|
-
|
286
|
-
|
287
|
-
self.seqno = 1
|
288
|
-
else:
|
289
|
-
last = qs[n - 1]
|
290
|
-
self.seqno = last.seqno + 1
|
285
|
+
last = qs[count - 1]
|
286
|
+
self.seqno = last.seqno + 1
|
291
287
|
|
292
288
|
def full_clean(self, *args, **kw):
|
293
289
|
if not self.seqno:
|
@@ -329,6 +325,14 @@ class Sequenced(Duplicable):
|
|
329
325
|
message=_("Renumbered {} of {} siblings.").format(n, qs.count()))
|
330
326
|
ar.set_response(refresh_all=True)
|
331
327
|
|
328
|
+
@fields.displayfield("⇵")
|
329
|
+
def dndreorder(self, ar):
|
330
|
+
"""A place holder column for drag and drop row reorder on :term:`React front end`
|
331
|
+
|
332
|
+
CAUTION: Do NOT rename this field, for react works on checking the name as dndreorder.
|
333
|
+
"""
|
334
|
+
return None
|
335
|
+
|
332
336
|
@fields.displayfield(_("Move"))
|
333
337
|
def move_buttons(obj, ar):
|
334
338
|
if ar is None:
|
@@ -96,7 +96,7 @@ class ExtRenderer(JsCacheRenderer):
|
|
96
96
|
super().__init__(plugin)
|
97
97
|
jsgen.register_converter(self.py2js_converter)
|
98
98
|
|
99
|
-
for s in
|
99
|
+
for s in ('green', 'blue', 'red', 'yellow', 'lightgrey'):
|
100
100
|
self.row_classes_map[s] = "x-grid3-row-%s" % s
|
101
101
|
|
102
102
|
self.prepare_layouts()
|
lino/modlib/gfks/fields.py
CHANGED
@@ -5,7 +5,6 @@
|
|
5
5
|
from django.db import models
|
6
6
|
from django.conf import settings
|
7
7
|
|
8
|
-
from lino.utils.choosers import chooser
|
9
8
|
from lino.core.utils import full_model_name
|
10
9
|
|
11
10
|
if settings.SITE.is_installed("contenttypes"):
|
@@ -31,6 +30,7 @@ if settings.SITE.is_installed("contenttypes"):
|
|
31
30
|
def contribute_to_class(self, cls, name, **kwargs):
|
32
31
|
# Automatically setup chooser and display field for ID field of
|
33
32
|
# generic foreign key.
|
33
|
+
from lino.utils.choosers import chooser
|
34
34
|
|
35
35
|
super().contribute_to_class(cls, name, **kwargs)
|
36
36
|
|
lino/modlib/jinja/renderer.py
CHANGED
lino/modlib/linod/models.py
CHANGED
@@ -32,7 +32,7 @@ class SystemTasks(dd.Table):
|
|
32
32
|
model = "linod.SystemTask"
|
33
33
|
order_by = ['seqno']
|
34
34
|
required_roles = dd.login_required(SiteStaff)
|
35
|
-
column_names = "seqno name log_level disabled status procedure *"
|
35
|
+
column_names = "seqno name log_level disabled status procedure dndreorder *"
|
36
36
|
detail_layout = """
|
37
37
|
seqno procedure
|
38
38
|
name
|
@@ -8,16 +8,14 @@ from lino.api import dd, rt, _
|
|
8
8
|
|
9
9
|
start_year = dd.get_plugin_setting("periods", "start_year", None)
|
10
10
|
|
11
|
+
|
11
12
|
def objects():
|
12
13
|
StoredYear = rt.models.periods.StoredYear
|
13
14
|
|
14
|
-
cfg = dd.plugins.periods
|
15
15
|
site = settings.SITE
|
16
16
|
if site.the_demo_date is not None:
|
17
17
|
if start_year > site.the_demo_date.year:
|
18
18
|
raise Exception("plugins.periods.start_year is after the_demo_date")
|
19
19
|
today = site.the_demo_date or datetime.date.today()
|
20
20
|
for y in range(start_year, today.year + 6):
|
21
|
-
# yield StoredYear.create_from_year(y)
|
22
21
|
yield StoredYear.get_or_create_from_date(datetime.date(y, today.month, today.day))
|
23
|
-
# StoredYears.add_item(StoredYear.year2value(y), str(y))
|
lino/modlib/periods/models.py
CHANGED
@@ -19,7 +19,6 @@ NEXT_YEAR_SEP = "/"
|
|
19
19
|
YEAR_PERIOD_SEP = "-"
|
20
20
|
|
21
21
|
|
22
|
-
|
23
22
|
class StoredYear(DateRange, Referrable):
|
24
23
|
|
25
24
|
class Meta:
|
@@ -30,7 +29,7 @@ class StoredYear(DateRange, Referrable):
|
|
30
29
|
|
31
30
|
preferred_foreignkey_width = 10
|
32
31
|
|
33
|
-
state = PeriodStates.field(
|
32
|
+
state = PeriodStates.field(blank=True)
|
34
33
|
|
35
34
|
@classmethod
|
36
35
|
def get_simple_parameters(cls):
|
@@ -80,9 +79,23 @@ class StoredYear(DateRange, Referrable):
|
|
80
79
|
obj.save()
|
81
80
|
return obj
|
82
81
|
|
82
|
+
def full_clean(self, *args, **kwargs):
|
83
|
+
if not self.state:
|
84
|
+
if self.start_date.year + 1 < dd.today().year:
|
85
|
+
self.state = PeriodStates.closed
|
86
|
+
else:
|
87
|
+
self.state = PeriodStates.open
|
88
|
+
super().full_clean(*args, **kwargs)
|
89
|
+
|
83
90
|
def __str__(self):
|
84
91
|
return self.ref
|
85
92
|
|
93
|
+
def get_next_row(self):
|
94
|
+
nextyear = self.start_date.replace(year=self.start_date.year+1)
|
95
|
+
ref = self.__class__.get_ref_for_date(nextyear)
|
96
|
+
return self.__class__.get_by_ref(ref, None)
|
97
|
+
# return self.__class__.get_or_create_from_date(nextyear)
|
98
|
+
|
86
99
|
|
87
100
|
class StoredPeriod(DateRange, Referrable):
|
88
101
|
|
@@ -94,8 +107,9 @@ class StoredPeriod(DateRange, Referrable):
|
|
94
107
|
|
95
108
|
preferred_foreignkey_width = 10
|
96
109
|
|
97
|
-
state = PeriodStates.field(
|
98
|
-
year = dd.ForeignKey('periods.StoredYear', blank=True,
|
110
|
+
state = PeriodStates.field(blank=True)
|
111
|
+
year = dd.ForeignKey('periods.StoredYear', blank=True,
|
112
|
+
null=True, related_name="periods")
|
99
113
|
remark = models.CharField(_("Remark"), max_length=250, blank=True)
|
100
114
|
|
101
115
|
@classmethod
|
@@ -107,7 +121,8 @@ class StoredPeriod(DateRange, Referrable):
|
|
107
121
|
@classmethod
|
108
122
|
def get_request_queryset(cls, ar):
|
109
123
|
qs = super().get_request_queryset(ar)
|
110
|
-
if (pv := ar.param_values) is None:
|
124
|
+
if (pv := ar.param_values) is None:
|
125
|
+
return qs
|
111
126
|
|
112
127
|
# if pv.start_date is None or pv.end_date is None:
|
113
128
|
# period = None
|
@@ -206,6 +221,8 @@ class StoredPeriod(DateRange, Referrable):
|
|
206
221
|
self.start_date = dd.today().replace(day=1)
|
207
222
|
if not self.year_id:
|
208
223
|
self.year = StoredYear.get_or_create_from_date(self.start_date)
|
224
|
+
if not self.state:
|
225
|
+
self.state = self.year.state
|
209
226
|
super().full_clean(*args, **kwargs)
|
210
227
|
|
211
228
|
def __str__(self):
|
@@ -230,11 +247,14 @@ class StoredPeriod(DateRange, Referrable):
|
|
230
247
|
return parts[1]
|
231
248
|
return self.ref
|
232
249
|
|
250
|
+
|
233
251
|
StoredPeriod.set_widget_options('ref', width=6)
|
234
252
|
|
253
|
+
|
235
254
|
def date2ref(d):
|
236
255
|
return StoredYear.get_ref_for_date(d) + YEAR_PERIOD_SEP + StoredPeriod.get_ref_for_date(d)
|
237
256
|
|
257
|
+
|
238
258
|
class StoredYears(dd.Table):
|
239
259
|
model = 'periods.StoredYear'
|
240
260
|
required_roles = dd.login_required(OfficeStaff)
|
@@ -244,6 +264,7 @@ class StoredYears(dd.Table):
|
|
244
264
|
# start_date end_date
|
245
265
|
# """
|
246
266
|
|
267
|
+
|
247
268
|
class StoredPeriods(dd.Table):
|
248
269
|
required_roles = dd.login_required(OfficeStaff)
|
249
270
|
model = 'periods.StoredPeriod'
|
@@ -2,9 +2,9 @@
|
|
2
2
|
# Copyright 2016-2024 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
|
-
import os
|
6
5
|
from pathlib import Path
|
7
|
-
from
|
6
|
+
from lino.modlib.jinja.choicelists import JinjaBuildMethod
|
7
|
+
from lino.modlib.printing.choicelists import BuildMethods
|
8
8
|
|
9
9
|
try:
|
10
10
|
from weasyprint import HTML
|
@@ -20,15 +20,6 @@ except ImportError:
|
|
20
20
|
BULMA_CSS = None
|
21
21
|
|
22
22
|
|
23
|
-
|
24
|
-
from django.conf import settings
|
25
|
-
from django.utils import translation
|
26
|
-
|
27
|
-
from lino.api import dd
|
28
|
-
from lino.modlib.jinja.choicelists import JinjaBuildMethod
|
29
|
-
from lino.modlib.printing.choicelists import BuildMethods
|
30
|
-
|
31
|
-
|
32
23
|
class WeasyBuildMethod(JinjaBuildMethod):
|
33
24
|
template_ext = ".weasy.html"
|
34
25
|
templates_name = "weasy"
|
@@ -77,7 +77,7 @@ div.recipient {
|
|
77
77
|
size: {%- block pagesize %}landscape{%- endblock %};
|
78
78
|
margin: {{dd.plugins.weasyprint.margin}}mm;
|
79
79
|
margin-bottom: {{dd.plugins.weasyprint.margin+dd.plugins.weasyprint.footer_height}}mm;
|
80
|
-
{%- if dd.plugins.weasyprint.top_right_image -%}
|
80
|
+
{%- if True or dd.plugins.weasyprint.top_right_image -%}
|
81
81
|
margin-top: {{dd.plugins.weasyprint.margin+dd.plugins.weasyprint.header_height}}mm;
|
82
82
|
{%- endif -%}
|
83
83
|
margin-left: {{dd.plugins.weasyprint.margin_left}}mm;
|
lino/utils/__init__.py
CHANGED
@@ -655,3 +655,23 @@ def logging_disabled(level):
|
|
655
655
|
yield
|
656
656
|
finally:
|
657
657
|
logging.disable(logging.NOTSET)
|
658
|
+
|
659
|
+
|
660
|
+
def nextref(ref):
|
661
|
+
"""
|
662
|
+
Increment the first number found in the string, preserving everything
|
663
|
+
thereafter.
|
664
|
+
|
665
|
+
Tested examples in :doc:`/topics/utils`.
|
666
|
+
"""
|
667
|
+
num = ""
|
668
|
+
suffix = ""
|
669
|
+
for i, c in enumerate(ref):
|
670
|
+
if c.isdigit():
|
671
|
+
num += c
|
672
|
+
else:
|
673
|
+
suffix = ref[i:]
|
674
|
+
break
|
675
|
+
if not num:
|
676
|
+
return None
|
677
|
+
return str(int(num)+1) + suffix
|
lino/utils/choosers.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright 2009-
|
1
|
+
# Copyright 2009-2025 Rumma & Ko Ltd
|
2
2
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
3
3
|
"""Extends the possibilities for defining choices for fields of a
|
4
4
|
Django model.
|
@@ -13,19 +13,18 @@ Example values in :doc:`/topics/utils`.
|
|
13
13
|
|
14
14
|
"""
|
15
15
|
|
16
|
+
import re
|
16
17
|
import decimal
|
17
18
|
import datetime
|
18
|
-
from dateutil import parser as dateparser
|
19
|
-
|
20
|
-
import re
|
21
19
|
|
22
|
-
|
23
|
-
r'^<a href="javascript:Lino\.(\w+\.\w+)\.detail\.run\(.*,\{ "record_id": (\w+) \}\)">.*</a>$'
|
24
|
-
)
|
25
|
-
|
26
|
-
from django.db import models
|
27
|
-
from django.conf import settings
|
20
|
+
from dateutil import parser as dateparser
|
28
21
|
from django.core.exceptions import BadRequest
|
22
|
+
from django.conf import settings
|
23
|
+
from django.db import models
|
24
|
+
|
25
|
+
from lino.core.utils import getrqdata
|
26
|
+
from lino.core import fields
|
27
|
+
from lino.core import constants
|
29
28
|
|
30
29
|
try:
|
31
30
|
from django.contrib.contenttypes.models import ContentType
|
@@ -33,10 +32,9 @@ except RuntimeError:
|
|
33
32
|
pass
|
34
33
|
# Happens when the site doesn't use contenttypes. Ignore silently.
|
35
34
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
from lino.core.utils import getrqdata
|
35
|
+
GFK_HACK = re.compile(
|
36
|
+
r'^<a href="javascript:Lino\.(\w+\.\w+)\.detail\.run\(.*,\{ "record_id": (\w+) \}\)">.*</a>$'
|
37
|
+
)
|
40
38
|
|
41
39
|
# class DataError(Exception):
|
42
40
|
# pass
|
@@ -257,6 +255,11 @@ class Chooser(FieldChooser):
|
|
257
255
|
if isinstance(field, fields.VirtualField):
|
258
256
|
selector = field.return_type
|
259
257
|
|
258
|
+
# TODO: move this to top and fix ImportError cannot import name
|
259
|
+
# 'chooser' from partially initialized module 'lino.utils.choosers'
|
260
|
+
# (most likely due to a circular import)
|
261
|
+
from lino.modlib.gfks.fields import GenericForeignKeyIdField
|
262
|
+
|
260
263
|
if isinstance(selector, ChoiceListField):
|
261
264
|
self.simple_values = getattr(meth, "simple_values", False)
|
262
265
|
self.instance_values = getattr(meth, "instance_values", True)
|
@@ -265,6 +268,8 @@ class Chooser(FieldChooser):
|
|
265
268
|
)
|
266
269
|
elif is_foreignkey(selector):
|
267
270
|
pass
|
271
|
+
elif isinstance(selector, GenericForeignKeyIdField):
|
272
|
+
pass
|
268
273
|
# elif isinstance(field, fields.VirtualField) and isinstance(
|
269
274
|
# field.return_type, models.ForeignKey
|
270
275
|
# ):
|
@@ -471,7 +476,7 @@ def _chooser(make, **options):
|
|
471
476
|
return fn(*args)
|
472
477
|
|
473
478
|
cp = options.pop(
|
474
|
-
"context_params", fn.__code__.co_varnames[1
|
479
|
+
"context_params", fn.__code__.co_varnames[1: fn.__code__.co_argcount]
|
475
480
|
)
|
476
481
|
wrapped.context_params = cp
|
477
482
|
for k, v in options.items():
|
@@ -518,6 +523,7 @@ def check_for_chooser(holder, field):
|
|
518
523
|
methname = field.name + "_choices"
|
519
524
|
m = getattr(holder, methname, None)
|
520
525
|
if m is not None:
|
526
|
+
# print(f"20250511 chooser for {field.name} in {holder} is {m}")
|
521
527
|
# if field.name.endswith('municipality'):
|
522
528
|
# print("20200524 check_for_chooser() found {} on {}", field.name, holder)
|
523
529
|
# 20200425 fix theoretical bug
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: lino
|
3
|
-
Version: 25.5.
|
3
|
+
Version: 25.5.1
|
4
4
|
Summary: A framework for writing desktop-like web applications using Django and ExtJS or React
|
5
5
|
Project-URL: Homepage, https://www.lino-framework.org
|
6
6
|
Project-URL: Repository, https://gitlab.com/lino-framework/lino
|
@@ -1,10 +1,10 @@
|
|
1
1
|
lino/.cvsignore,sha256=1vrrWoP-WD8hPfCszHHIiJEi8KUMRCt5WvoKB9TSB1k,28
|
2
2
|
lino/SciTEDirectory.properties,sha256=rCYi_e-6h8Yx5DwXhAa6MBPlVINcl6Vv9BQDYZV2_go,28
|
3
|
-
lino/__init__.py,sha256=
|
3
|
+
lino/__init__.py,sha256=uIdvk33nJCfbsJGNg2B_VrDVh7GSL-ASrQK6Lh7rbLc,6176
|
4
4
|
lino/ad.py,sha256=AQ-vJ4scac1mx3xegXezxnxyOQpV-a0q3VFMJSDbj2s,142
|
5
5
|
lino/apps.py,sha256=ECq-dPARDkuhngwNrcipse3b4Irj70HxJs44uWEZFc4,27
|
6
6
|
lino/hello.py,sha256=7-PJg7PnEiznyETqGjOwXcKh8rda0qLetpbS2gvRYy0,532
|
7
|
-
lino/help_texts.py,sha256
|
7
|
+
lino/help_texts.py,sha256=-PiZ-hMm_JKjoD6591y5A4_hyp2NuVFBFoyn_5mWsbU,92266
|
8
8
|
lino/api/__init__.py,sha256=WmzHU-rHdZ68se_nI0SmepQTGE8-cd9tPpovHRH9aag,512
|
9
9
|
lino/api/ad.py,sha256=F6SrcKPRRalHKOZ7QLwsRWGq9hhykQIeo0b85cEk9NQ,314
|
10
10
|
lino/api/dd.py,sha256=-mxiSJS27LGCWyOgboA8qDudTkE9vg9vmUGOT08Hq6A,7410
|
@@ -28,31 +28,31 @@ lino/config/unused/403.html,sha256=ePwDIUXhz1iD8xXWWyt5xEvpcGIHU4LMnXma8x0ik1c,2
|
|
28
28
|
lino/config/unused/404.html,sha256=GOJrAyF6NcM69ETdSHgjff_-lvYs_-bOYhyZBem7x3I,220
|
29
29
|
lino/config/unused/500.html,sha256=aWmP37uPoMS-PJgPuBloxdx0nEreU7AvkXxsex3yVYs,544
|
30
30
|
lino/core/__init__.py,sha256=T7106QxQpa3jXAouGTIer6AXEwpkJ0NAQ9B7Q3-K6qE,686
|
31
|
-
lino/core/actions.py,sha256=
|
32
|
-
lino/core/actors.py,sha256=
|
31
|
+
lino/core/actions.py,sha256=GIBiuu6bIMl2g0Y9-LWLhvTe2qHOcRGfHjBvl0vyrzU,46542
|
32
|
+
lino/core/actors.py,sha256=_Cl25nw65NK7me-wIHTJRh6iqcb6m12nUbvvQrLcjDk,74992
|
33
33
|
lino/core/boundaction.py,sha256=sPRoBNjKApMUSBASu86aVVFhs7egNd6kYyLOBwGBDSs,7048
|
34
34
|
lino/core/callbacks.py,sha256=uu1-znzxVDD-JETUebw-hYsNg_9ExQb1vfwbc7Psjro,7549
|
35
|
-
lino/core/choicelists.py,sha256=
|
35
|
+
lino/core/choicelists.py,sha256=5b_FpURG1ZNwEGfuvCd9FtI3agCHJnhj31ZxaXcur3A,36504
|
36
36
|
lino/core/classproperty.py,sha256=_E95WPAs7BWbAuFpPvoYM2ZwW_mbq3rvF7o43WsMq_8,4316
|
37
37
|
lino/core/constants.py,sha256=chvG1TrwD2gVMmL4nTOZtO8NcffcclcUv3zBE8mMoiQ,4503
|
38
38
|
lino/core/dashboard.py,sha256=1ASWZ9I1LQBUJZ0JKiwW_g_1Pix3jb4SWUFC2cUM23g,6537
|
39
|
-
lino/core/dbtables.py,sha256=
|
39
|
+
lino/core/dbtables.py,sha256=6vTjLtwYXtFMSe_-G-5OVcb7kOcRrYFh3nyjJUHdpVw,29127
|
40
40
|
lino/core/dbutils.py,sha256=_QHcWd-ajLUwt5G8uOp8d47lZQKD3VseHnqKJke18rA,263
|
41
41
|
lino/core/ddh.py,sha256=dYScxWKTOCDEgow7wJNJe812ESasmmITPK2ovraBQno,3172
|
42
42
|
lino/core/diff.py,sha256=XQ-oQQDS_v3kXd4eRP9Hwr5UCgp-TPZIPVav9ZblUno,5882
|
43
|
-
lino/core/elems.py,sha256=
|
43
|
+
lino/core/elems.py,sha256=LeNPC8SBFobRbwy6LhmfkDcZhSbvcnsC3oVNprhak2Q,109013
|
44
44
|
lino/core/exceptions.py,sha256=QDxDo5cllSyXQ8VWet9hGXzNadxCOmwMVrFXc6V-vpE,665
|
45
|
-
lino/core/fields.py,sha256=
|
45
|
+
lino/core/fields.py,sha256=rgpuK51TTJHeIq0KE97F6FAWRCYx-nLFTerQTXKquQ4,60130
|
46
46
|
lino/core/frames.py,sha256=ISxgq9zyZfqW3tDZMWdKi9Ij455lT_81qBH0xex0bfE,1161
|
47
47
|
lino/core/gfks.py,sha256=6VXn2FSIXOrwVq0stfbPevT37EWg1tg4Fn-HMNVnbmk,1970
|
48
48
|
lino/core/help.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
49
49
|
lino/core/inject.py,sha256=Qd_PGEn0yMXNYVPI0wCv1vvo2CNdlPkyoBmKZELOtGM,13422
|
50
|
-
lino/core/kernel.py,sha256=
|
50
|
+
lino/core/kernel.py,sha256=jJ2bZw77kFX_CVI0M0rdoj0bsTK2GIwnSn2RTt7-Tec,48025
|
51
51
|
lino/core/keyboard.py,sha256=W3jA6qtB5HMppoNnd_6PgIM7ZlyHilJEhBvdeZTY7Xk,1283
|
52
52
|
lino/core/layouts.py,sha256=VT0xcDB7JKSsNm2UOybAwJw3zOie57sRagRYlyA7nkg,28697
|
53
53
|
lino/core/menus.py,sha256=W0Co9K-ayvfX5Zt5rgSxJrFRejtiYrwIR5EecdYXPNc,10857
|
54
54
|
lino/core/merge.py,sha256=sKtTeZtHdoDKerdHj4NXuXXNzpKDsfdPaiq-CY0NqQc,9094
|
55
|
-
lino/core/model.py,sha256=
|
55
|
+
lino/core/model.py,sha256=XSYjml_8WPjUU_LgGIH1qmPIwlIlQ0cjNFdN5A_ULko,36920
|
56
56
|
lino/core/permissions.py,sha256=Fnemz3NwWz21X0YATI9Q7ba2FcAdg-EMLHjIcbt_AVU,6840
|
57
57
|
lino/core/plugin.py,sha256=n_f5dSy4vqamnyzpNnaNcTlUp2EAgaAVxIJ5EHG7aHc,6837
|
58
58
|
lino/core/renderer.py,sha256=C00J0L41hLv9b2sAzqSSrT0Lz5Fc78JnwHiq9LqF81c,47310
|
@@ -60,8 +60,8 @@ lino/core/requests.py,sha256=aIT8DsWVWwYQWHf7xX7SbbUf0s_8dWfayR3104VDrnQ,95833
|
|
60
60
|
lino/core/roles.py,sha256=PXwk436xUupxdbJcygRSYFu7ixfKjAJPQRUQ8sy0lB0,4425
|
61
61
|
lino/core/signals.py,sha256=0JT89mkjSbRm57QZcSI9DoThoKUGkyi-egNhuLUKEds,948
|
62
62
|
lino/core/site.py,sha256=8qV5nEPuUaA7ViEcFOeOGPpzILrmWKOFS9MGPjqFcAs,82713
|
63
|
-
lino/core/store.py,sha256=
|
64
|
-
lino/core/tables.py,sha256=
|
63
|
+
lino/core/store.py,sha256=ibshCPBKd0zNSoAfMYx1MaqHXggE-O4zqiSUSlY-x68,51444
|
64
|
+
lino/core/tables.py,sha256=3IxOHtnN_5fkkLp5-TCBM_Z61aBGzynwIhvAEY71UcM,24476
|
65
65
|
lino/core/urls.py,sha256=06QlmN1vpxjmb5snO3SPpP6lX1pMdE60bTiBiC77_vQ,2677
|
66
66
|
lino/core/user_types.py,sha256=0iSYmzr2M9v2Mn2y6hzAZeqareUT-gD7l3MfIPyG9ZI,867
|
67
67
|
lino/core/userprefs.py,sha256=cmufIS9xJErKDrw05uoWtQTUR6WRWIGkU1KdAqzNr5M,2850
|
@@ -117,14 +117,14 @@ lino/management/commands/syncscreenshots.py,sha256=XYZhqfm5_RwJzVFNGhHJKucl4j6T6
|
|
117
117
|
lino/management/commands/update_conf.py,sha256=saAaQdPhn3mNOoHcBxOFSf_vBEgM-aopTHq1sJN20Bo,1026
|
118
118
|
lino/mixins/__init__.py,sha256=7_gW-TzHryL9hvcOx90Op-uBGvivtEj4e6bfNp6j_OE,8854
|
119
119
|
lino/mixins/dupable.py,sha256=9DNZ9xsgSFsxchqzlo86jQVecXABuDeEZ62tamj-X9A,10235
|
120
|
-
lino/mixins/duplicable.py,sha256=
|
120
|
+
lino/mixins/duplicable.py,sha256=kraLul9nZb2oWi_MyTdwoSU2IQnHgTb_snLaMmGqgyQ,4436
|
121
121
|
lino/mixins/human.py,sha256=YDIfIHHAaVmzd3uGsJp_vDvkaBWOp09I7i4AGNy9YsQ,13255
|
122
122
|
lino/mixins/periods.py,sha256=iFqUCUZlgUW2GmEHRl9suwJedztrXLluQhgFpu7Uj54,11479
|
123
123
|
lino/mixins/polymorphic.py,sha256=MLbfOeIYRoDZO4048X2oWhG5cxds2pLkwciXcw1xjVQ,9393
|
124
124
|
lino/mixins/printable.py,sha256=4U8M1lrTjUeuaPwrcWoanCBo53iAxiNpSTsVctI-gI0,199
|
125
|
-
lino/mixins/ref.py,sha256=
|
126
|
-
lino/mixins/registrable.py,sha256=
|
127
|
-
lino/mixins/sequenced.py,sha256=
|
125
|
+
lino/mixins/ref.py,sha256=qV8CprGCvwzzWTl6LQc9I1RwD8pziD0F7Ykoaznm8wM,5550
|
126
|
+
lino/mixins/registrable.py,sha256=37usXcHtz_F8rJtZ0fCS4_KZFQ87fSDXO-GPYEZ_IzY,7210
|
127
|
+
lino/mixins/sequenced.py,sha256=GRw8KmCQyEfrXvkDf-moND_tHKcsFLhzLzQ6_s94tHM,16605
|
128
128
|
lino/modlib/__init__.py,sha256=cO31gNu2oRkp7o2v3D9gK2H7j4jF9rbVyPxPZhZQwrQ,940
|
129
129
|
lino/modlib/about/__init__.py,sha256=jhqGQIXU1o7KkmmQjfwPKJc3buibB09Fy55carAmi7U,342
|
130
130
|
lino/modlib/about/choicelists.py,sha256=2bxDb2u7cFacBOgLoEWrMmzQ4BJ3x1pmhdgqxzUp-Rw,1424
|
@@ -187,7 +187,7 @@ lino/modlib/dupable/models.py,sha256=0watviKwTiVwlArC54V3IxVVfcB1Yg5kO6ed2xCM9a0
|
|
187
187
|
lino/modlib/export_excel/__init__.py,sha256=HrsrhXjIMvMHRGu8whH3A_WijZWrH35p2cQsFXK60DY,356
|
188
188
|
lino/modlib/export_excel/models.py,sha256=A-lFS-xFDSPHcVbY0OI7VsuGr82jJyLDhXH2Dcv80Os,5039
|
189
189
|
lino/modlib/extjs/__init__.py,sha256=6UBWAWSROwy3DfTXQmVUVJTF6eZ_e2k3BEfE4wtqVhU,10172
|
190
|
-
lino/modlib/extjs/ext_renderer.py,sha256=
|
190
|
+
lino/modlib/extjs/ext_renderer.py,sha256=1qEQ32fNDz6cXWgKTUc2qpfAjwrLjSRcWYk94A2odAo,60632
|
191
191
|
lino/modlib/extjs/views.py,sha256=CrX_tPshJtSkHT7raDDqn4B_XYamujRs-CgLzY4CBxg,26299
|
192
192
|
lino/modlib/extjs/config/extjs/index.html,sha256=jO5hdNpFSkm9t0xhHD5hc8Hw1fSr6xb3zYq9aMyOI7Q,8603
|
193
193
|
lino/modlib/extjs/config/extjs/linoweb.js,sha256=I4VYGmkK4htqZvHM9g-6psJF3pp7SvgHEI0I02Sxpvo,175127
|
@@ -3490,7 +3490,7 @@ lino/modlib/forms/models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3490
3490
|
lino/modlib/forms/renderer.py,sha256=KLMAyDPLpWlRCzzQ4F4aS2bs5birR_JaFQu6lQX-ZNk,2406
|
3491
3491
|
lino/modlib/forms/views.py,sha256=L8U8LKFB1bP1q2NiAcRkZvynT_uw7yb93HIwA3TaXTs,10313
|
3492
3492
|
lino/modlib/gfks/__init__.py,sha256=2f34DqbWXWUxE_y_0LqLfkpoyZ-cqQucg4xZkI2H3VY,1247
|
3493
|
-
lino/modlib/gfks/fields.py,sha256=
|
3493
|
+
lino/modlib/gfks/fields.py,sha256=csvdt8U1GbyJ9iM6gbCWq5gFanbLJipM5Kw80wwp-Kw,3251
|
3494
3494
|
lino/modlib/gfks/mixins.py,sha256=BcITVETBR7zVj684diZGCii3rzm7lgrgzr2euy-D-iw,2626
|
3495
3495
|
lino/modlib/gfks/models.py,sha256=bDbuvtpSW-wxNWLC3pKWsDQPyN4g6MFMTS-66aQ2DX8,6723
|
3496
3496
|
lino/modlib/help/__init__.py,sha256=PlThatoYB6lThNahWkVL2ZatimW0d_9LAPTZIE7hiuE,4434
|
@@ -3519,7 +3519,7 @@ lino/modlib/jinja/choicelists.py,sha256=QHjWQWLnJCKSGnLIKeGqnCw41JYvcbTkCeXjBpWh
|
|
3519
3519
|
lino/modlib/jinja/loader.py,sha256=MX027X_UuQPqq0wOUr06QnOkdTzGpksNv0Om1CGp61I,1765
|
3520
3520
|
lino/modlib/jinja/mixins.py,sha256=YqvNt1JB7as6IohBoyP8DqHldxmg9yOfrN27V5cn7Ho,2913
|
3521
3521
|
lino/modlib/jinja/models.py,sha256=vXNFS78qP-qIzeSmnXJNOpvW_IfH1h6hhPgYjfkvvD0,207
|
3522
|
-
lino/modlib/jinja/renderer.py,sha256=
|
3522
|
+
lino/modlib/jinja/renderer.py,sha256=M7qrPwf_n730YoGXNQAnaJSBvD2lw-hez2_1YPIqSHo,6198
|
3523
3523
|
lino/modlib/jinja/config/jinja/status.jinja.rst,sha256=XEsfXd82B0fLsBfds5-pXdeDWVr4ccTv7WyGa9ayigk,312
|
3524
3524
|
lino/modlib/jinja/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3525
3525
|
lino/modlib/jinja/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -3535,7 +3535,7 @@ lino/modlib/linod/__init__.py,sha256=efmj_Kz3OO2zF1lvs7P459iufYGimH1-6Ge6Cbq85tQ
|
|
3535
3535
|
lino/modlib/linod/choicelists.py,sha256=Cu82s1QpcGFmKUXJsg-7TSqpaESBCZKOEfxzFlJP06I,2626
|
3536
3536
|
lino/modlib/linod/consumers.py,sha256=XBjA1fflJ-e9yWRMKXyQAhrOklYzs5JRhEeGMOKWFqM,6730
|
3537
3537
|
lino/modlib/linod/mixins.py,sha256=Dff7rX5Ih0uJul0jID6tdY5CIZa6z6iq9feXIjNohkQ,11691
|
3538
|
-
lino/modlib/linod/models.py,sha256=
|
3538
|
+
lino/modlib/linod/models.py,sha256=Jj9N84793qsx5QmBrJ8LV2hiuqnaAKwQuAGiMF-t104,2372
|
3539
3539
|
lino/modlib/linod/routing.py,sha256=3pYJT6FbaVMj6rKkDVv3E5VTFFc9nglIDeo6dgAKu8Q,2399
|
3540
3540
|
lino/modlib/linod/utils.py,sha256=dE973Xib6Be1DvNsZ0M5wzY_jpkk35R21WKs-jQPorM,339
|
3541
3541
|
lino/modlib/linod/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -3577,8 +3577,8 @@ lino/modlib/office/roles.py,sha256=oQWTZ-_9_vssc9QW5A0YspMjG_V5gCiHSU0eE0AIH30,3
|
|
3577
3577
|
lino/modlib/periods/__init__.py,sha256=MFTI4YTYw3zTxYVlD568rBxn02e_J9Yn10uZ6U5W-uQ,1069
|
3578
3578
|
lino/modlib/periods/choicelists.py,sha256=_t_l40FlXYAyRnlOZzh4DR5wMCM1nIWiIfS7QKbXkmw,1304
|
3579
3579
|
lino/modlib/periods/mixins.py,sha256=QQXtu1Z6HjqDlL_xMM98FR7PQGKhYgjslhusOiWwPDA,4271
|
3580
|
-
lino/modlib/periods/models.py,sha256=
|
3581
|
-
lino/modlib/periods/fixtures/std.py,sha256=
|
3580
|
+
lino/modlib/periods/models.py,sha256=ICjFPH1To5UwH8Bd_EWm2A5q-R_q0OGvilGKZzLr6uY,9107
|
3581
|
+
lino/modlib/periods/fixtures/std.py,sha256=aWzt-frGjzPDwQ2pCKU1nT3oE4xzm7AQ8uLTJqSnS54,741
|
3582
3582
|
lino/modlib/printing/__init__.py,sha256=u1fq44d073-IDH_t8hWs1sQdlAHdsCP85sfEOMSW5L4,689
|
3583
3583
|
lino/modlib/printing/actions.py,sha256=2-JORKcjJYuzK2kYmhqZl0gRR-4CrG7ul8mcFNfYYAI,11766
|
3584
3584
|
lino/modlib/printing/choicelists.py,sha256=DM929pej7NUi1gm38nUr0t3-VANV95eqCLeW5ubh8y8,9712
|
@@ -4422,10 +4422,10 @@ lino/modlib/users/fixtures/demo.py,sha256=YHPhvjqAh-V9WHgFct2GQlQATZmS-W3Nry-X6m
|
|
4422
4422
|
lino/modlib/users/fixtures/demo2.py,sha256=j2ke91wvpHs3kHpeztzV3nOG4rJvavkHv2YJo0dISdI,495
|
4423
4423
|
lino/modlib/users/fixtures/demo_users.py,sha256=FJz5gW95PbgxrPD8BMSVnpA8SJJSPWtjyi3LMdytd5o,1805
|
4424
4424
|
lino/modlib/users/fixtures/std.py,sha256=Eo_TdqFC7NPryLeGRfp-nbOXw3hDqxTUpddFTxUuZ74,712
|
4425
|
-
lino/modlib/weasyprint/__init__.py,sha256=
|
4426
|
-
lino/modlib/weasyprint/choicelists.py,sha256=
|
4425
|
+
lino/modlib/weasyprint/__init__.py,sha256=i0xDsTTIAHGtoStybEv_YNCFJmxGeCy-e5qAyDWWygg,2285
|
4426
|
+
lino/modlib/weasyprint/choicelists.py,sha256=A3zXUGoiU06DuC8PIM2zS3lnKQk_pahsfXPRAQfMLog,1266
|
4427
4427
|
lino/modlib/weasyprint/models.py,sha256=op6CRRBC8NatqGgGdQHU4zcVG4fu4mRS9Mz8STG3B3g,168
|
4428
|
-
lino/modlib/weasyprint/config/weasyprint/base.weasy.html,sha256=
|
4428
|
+
lino/modlib/weasyprint/config/weasyprint/base.weasy.html,sha256=zs2QpK7DX-uGBYs30eJAFlPyyI2UySyt_Ee17twNcgY,4617
|
4429
4429
|
lino/modlib/wkhtmltopdf/__init__.py,sha256=1nqwVpOQH4YMhegnzrcfvXW_Xy9CIdHBHzrNvDGyVxg,773
|
4430
4430
|
lino/modlib/wkhtmltopdf/choicelists.py,sha256=Mq7LySs-HJIXnyUHN5PR55nQyg2cgPjEQuN9JUhBmUY,1818
|
4431
4431
|
lino/modlib/wkhtmltopdf/models.py,sha256=T7lHSSQKNcUWceNnNzq_bKEguXQ1THK5qyCDgeV6xfM,294
|
@@ -4579,10 +4579,10 @@ lino/templates_old/404.html,sha256=9O5EJgULwLws0X1LjNig3xT4l9Hw04MBIGswD-EAlnw,2
|
|
4579
4579
|
lino/templates_old/500.html,sha256=inOR744w4FGJM_fCSQcnlk-OIYQpaBTxUQWgXQozon4,496
|
4580
4580
|
lino/templates_old/base.html,sha256=qYqj5-u1UPtpatrFkqBr3MnwS0oFUXCyQRcuNZczDfk,1641
|
4581
4581
|
lino/templates_old/base_site.html,sha256=NcLEk0kBT1b-SrhoGpDPUej7NExqJ9-dP1kbrvwBzrs,255
|
4582
|
-
lino/utils/__init__.py,sha256=
|
4582
|
+
lino/utils/__init__.py,sha256=28o4xeRyrgkRVsUoAd0C3RJhhpIUSMNRU_-d44PulXs,17249
|
4583
4583
|
lino/utils/addressable.py,sha256=o7bmLbyvrmOoAT478s7XqjWKvnZ7zSXj4k7Xf0ccqf8,2213
|
4584
4584
|
lino/utils/ajax.py,sha256=npCS0WumhTQlBzXxQPKnp2sYCRcPsYcbFqzE2ykVc4Q,3254
|
4585
|
-
lino/utils/choosers.py,sha256=
|
4585
|
+
lino/utils/choosers.py,sha256=8-D4ccUqxveu5r7lHJdunywEkwMT7E5tYsPKPk6Neto,17994
|
4586
4586
|
lino/utils/code.py,sha256=-2vc8npHQ5jsrRqzxmjRZZ8FWY7QJ7-sRg7-ZhOsUEU,7053
|
4587
4587
|
lino/utils/config.py,sha256=gtaJURPOwHyV_AW7i7_vin3KTj3UwZa4iviDbldwXGE,8568
|
4588
4588
|
lino/utils/cycler.py,sha256=2LGMhMJX5At5ln4yZvmNleWROs-CA_YE_UCzxzvxK4U,1548
|
@@ -4635,8 +4635,8 @@ lino/utils/xml.py,sha256=EGDnO1UaREst9fS7KTESdbHnrrVCwKbRQdvut6B6GmQ,1612
|
|
4635
4635
|
lino/utils/mldbc/__init__.py,sha256=QqWRlzeXaOmFfbCk-vTY3SZMn1-FCf67XnpZdd_Nim0,1134
|
4636
4636
|
lino/utils/mldbc/fields.py,sha256=tAX8G5UKigr9c6g0F3ARIjZZtg406mdaZ--PWSbiH9E,2873
|
4637
4637
|
lino/utils/mldbc/mixins.py,sha256=CkYe5jDa7xp9fJq_V8zcZf8ocxgIjUgHc9KZccvA_Yw,1945
|
4638
|
-
lino-25.5.
|
4639
|
-
lino-25.5.
|
4640
|
-
lino-25.5.
|
4641
|
-
lino-25.5.
|
4642
|
-
lino-25.5.
|
4638
|
+
lino-25.5.1.dist-info/METADATA,sha256=zZMb_Y5CgBuAGaAwtzKtOzuEE1Fp2o8KrE-VAZoKD78,42534
|
4639
|
+
lino-25.5.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
4640
|
+
lino-25.5.1.dist-info/licenses/AUTHORS.rst,sha256=8VEm_G4HOmYEa4oi1nVoKKsdo4JanekEJCefWd2E8vk,981
|
4641
|
+
lino-25.5.1.dist-info/licenses/COPYING,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
4642
|
+
lino-25.5.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|