lino 25.2.3__py3-none-any.whl → 25.3.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/api/dd.py +11 -48
- lino/api/doctest.py +34 -36
- lino/core/actions.py +25 -23
- lino/core/actors.py +37 -17
- lino/core/choicelists.py +10 -8
- lino/core/dbtables.py +1 -1
- lino/core/elems.py +46 -30
- lino/core/fields.py +19 -9
- lino/core/inject.py +7 -6
- lino/core/kernel.py +26 -66
- lino/core/model.py +44 -31
- lino/core/plugin.py +4 -4
- lino/core/requests.py +76 -55
- lino/core/site.py +84 -30
- lino/core/store.py +5 -2
- lino/core/utils.py +12 -7
- lino/help_texts.py +3 -8
- lino/management/commands/prep.py +1 -1
- lino/mixins/duplicable.py +6 -4
- lino/mixins/sequenced.py +17 -6
- lino/modlib/__init__.py +0 -2
- lino/modlib/changes/models.py +21 -10
- lino/modlib/checkdata/models.py +59 -24
- lino/modlib/comments/fixtures/demo2.py +12 -3
- lino/modlib/comments/models.py +7 -7
- lino/modlib/comments/ui.py +8 -5
- lino/modlib/export_excel/models.py +7 -5
- lino/modlib/extjs/views.py +39 -20
- lino/modlib/help/management/commands/makehelp.py +5 -2
- lino/modlib/jinja/mixins.py +25 -14
- lino/modlib/linod/__init__.py +1 -0
- lino/modlib/linod/choicelists.py +21 -0
- lino/modlib/linod/consumers.py +13 -4
- lino/modlib/linod/management/commands/linod.py +6 -2
- lino/modlib/linod/mixins.py +16 -11
- lino/modlib/linod/models.py +4 -2
- lino/modlib/notify/models.py +18 -10
- lino/modlib/printing/actions.py +41 -30
- lino/modlib/printing/choicelists.py +11 -9
- lino/modlib/printing/mixins.py +25 -20
- lino/modlib/publisher/models.py +5 -5
- lino/modlib/summaries/models.py +3 -2
- lino/modlib/system/models.py +28 -29
- lino/modlib/uploads/__init__.py +5 -5
- lino/modlib/uploads/actions.py +2 -8
- lino/modlib/uploads/choicelists.py +10 -10
- lino/modlib/uploads/fixtures/std.py +17 -0
- lino/modlib/uploads/mixins.py +20 -8
- lino/modlib/uploads/models.py +60 -35
- lino/modlib/uploads/ui.py +10 -7
- lino/utils/media.py +45 -23
- lino/utils/report.py +5 -4
- lino/utils/soup.py +22 -4
- {lino-25.2.3.dist-info → lino-25.3.1.dist-info}/METADATA +1 -1
- {lino-25.2.3.dist-info → lino-25.3.1.dist-info}/RECORD +59 -80
- lino/mixins/uploadable.py +0 -3
- lino/sandbox/bcss/PerformInvestigation.py +0 -2260
- lino/sandbox/bcss/SSDNReply.py +0 -3924
- lino/sandbox/bcss/SSDNRequest.py +0 -3723
- lino/sandbox/bcss/__init__.py +0 -0
- lino/sandbox/bcss/readme.txt +0 -1
- lino/sandbox/bcss/test.py +0 -92
- lino/sandbox/bcss/test2.py +0 -128
- lino/sandbox/bcss/test3.py +0 -161
- lino/sandbox/bcss/test4.py +0 -167
- lino/sandbox/contacts/__init__.py +0 -0
- lino/sandbox/contacts/fixtures/__init__.py +0 -0
- lino/sandbox/contacts/fixtures/demo.py +0 -365
- lino/sandbox/contacts/manage.py +0 -10
- lino/sandbox/contacts/models.py +0 -395
- lino/sandbox/contacts/settings.py +0 -67
- lino/sandbox/tx25/XSD/RetrieveTIGroupsV3.wsdl +0 -65
- lino/sandbox/tx25/XSD/RetrieveTIGroupsV3.xsd +0 -286
- lino/sandbox/tx25/XSD/rn25_Release201104.xsd +0 -2855
- lino/sandbox/tx25/xsd2py1.py +0 -68
- lino/sandbox/tx25/xsd2py2.py +0 -62
- lino/sandbox/tx25/xsd2py3.py +0 -56
- {lino-25.2.3.dist-info → lino-25.3.1.dist-info}/WHEEL +0 -0
- {lino-25.2.3.dist-info → lino-25.3.1.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.2.3.dist-info → lino-25.3.1.dist-info}/licenses/COPYING +0 -0
lino/__init__.py
CHANGED
lino/api/dd.py
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2011-
|
2
|
+
# Copyright 2011-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
|
+
# from lino.modlib.linod.choicelists import background_task, schedule_often, schedule_daily
|
6
|
+
from lino.core.roles import SiteStaff, SiteUser, SiteAdmin, login_required
|
7
|
+
from django.utils import translation
|
8
|
+
from importlib import import_module
|
9
|
+
from lino.modlib.system.choicelists import Genders, PeriodEvents, YesNo
|
10
|
+
from lino.utils.mldbc.fields import BabelCharField, LanguageField
|
11
|
+
from lino.utils.mldbc.fields import BabelTextField
|
12
|
+
from lino.utils.format_date import fdl as dtosl
|
5
13
|
from lino import logger
|
6
14
|
|
7
15
|
# import logging ; logger = logging.getLogger(__name__)
|
@@ -96,7 +104,8 @@ from lino.core.fields import CharField
|
|
96
104
|
from lino.core.utils import babelkw
|
97
105
|
|
98
106
|
# from lino.core.utils import babelattr
|
99
|
-
|
107
|
+
# alias for babelkw for backward compat
|
108
|
+
from lino.core.utils import babel_values
|
100
109
|
|
101
110
|
from lino.utils.choosers import chooser, action_chooser
|
102
111
|
|
@@ -156,18 +165,11 @@ def fds(d):
|
|
156
165
|
|
157
166
|
# backward compatibility
|
158
167
|
dtos = fds
|
159
|
-
from lino.utils.format_date import fdl as dtosl
|
160
168
|
|
161
169
|
babelitem = settings.SITE.babelitem
|
162
170
|
field2kw = settings.SITE.field2kw
|
163
171
|
# urlkwargs = settings.SITE.urlkwargs
|
164
172
|
|
165
|
-
from lino.utils.mldbc.fields import BabelTextField
|
166
|
-
from lino.utils.mldbc.fields import BabelCharField, LanguageField
|
167
|
-
|
168
|
-
from lino.modlib.system.choicelists import Genders, PeriodEvents, YesNo
|
169
|
-
|
170
|
-
from importlib import import_module
|
171
173
|
|
172
174
|
decfmt = settings.SITE.decfmt
|
173
175
|
str2kw = settings.SITE.str2kw
|
@@ -199,48 +201,9 @@ babelattr = settings.SITE.babelattr
|
|
199
201
|
plugins = settings.SITE.plugins
|
200
202
|
format_currency = settings.SITE.format_currency
|
201
203
|
|
202
|
-
from django.utils import translation
|
203
204
|
|
204
205
|
get_language = translation.get_language
|
205
206
|
|
206
|
-
from lino.core.roles import SiteStaff, SiteUser, SiteAdmin, login_required
|
207
|
-
|
208
|
-
from lino.modlib.linod.choicelists import Procedures
|
209
|
-
|
210
|
-
|
211
|
-
def background_task(**kwargs):
|
212
|
-
"""
|
213
|
-
Register the decorated function as a :term:`background task`.
|
214
|
-
|
215
|
-
Keyword arguments are used as default values when checkdata creates a
|
216
|
-
:class:`lino.modlib.linod.SystemTask` instance for this procedure.
|
217
|
-
|
218
|
-
Except for the special keyword ``class_name``, which defaults to
|
219
|
-
"linod.SystemTask". It is used by :mod:`lino_xl.lib.invoicing` to register a
|
220
|
-
procedure that will create an :term:`invoicing task` instead of a normal
|
221
|
-
:term:`background task`. :class:`lino_xl.lib.invoicing.InvoicingTask`
|
222
|
-
instead of :class:`lino.modlib.linod.SystemTask`.
|
223
|
-
|
224
|
-
"""
|
225
|
-
if "class_name" not in kwargs:
|
226
|
-
kwargs["class_name"] = "linod.SystemTask"
|
227
|
-
|
228
|
-
def decorator(func):
|
229
|
-
Procedures.add_item(func, **kwargs)
|
230
|
-
return func
|
231
|
-
|
232
|
-
return decorator
|
233
|
-
|
234
|
-
|
235
|
-
def schedule_often(every=10, **kwargs):
|
236
|
-
kwargs.update(every_unit="secondly", every=every)
|
237
|
-
return background_task(**kwargs)
|
238
|
-
|
239
|
-
|
240
|
-
def schedule_daily(**kwargs):
|
241
|
-
kwargs.update(every_unit="daily", every=1)
|
242
|
-
return background_task(**kwargs)
|
243
|
-
|
244
207
|
|
245
208
|
def auto_height(n):
|
246
209
|
"""
|
lino/api/doctest.py
CHANGED
@@ -14,6 +14,38 @@ tested document. It includes
|
|
14
14
|
|
15
15
|
"""
|
16
16
|
|
17
|
+
from lino.core.boundaction import BoundAction
|
18
|
+
from lino.core.tables import AbstractTable
|
19
|
+
from lino.core.actions import Action
|
20
|
+
from django.db.models import Model
|
21
|
+
from lino.core.layouts import BaseLayout
|
22
|
+
from lino.core.actions import register_params
|
23
|
+
from lino.core.actions import ShowTable
|
24
|
+
from lino.core.menus import Menu
|
25
|
+
from lino.utils.html import html2text
|
26
|
+
from lino.core.utils import full_model_name, get_models
|
27
|
+
from lino.utils.diag import visible_for
|
28
|
+
from lino.sphinxcontrib.actordoc import menuselection_text
|
29
|
+
from lino import logger
|
30
|
+
from lino.core.menus import find_menu_item
|
31
|
+
from lino.core import constants
|
32
|
+
from lino.core import actors, kernel
|
33
|
+
from lino.utils.sql import sql_summary
|
34
|
+
from lino.utils import diag
|
35
|
+
from lino.utils.diag import analyzer
|
36
|
+
from lino.utils.html import E, tostring, to_rst
|
37
|
+
from lino.utils import i2d
|
38
|
+
from lino.utils import AttrDict
|
39
|
+
from rstgen.utils import unindent, rmu, sixprint
|
40
|
+
from rstgen import attrtable
|
41
|
+
import rstgen
|
42
|
+
import pytest
|
43
|
+
from django.db import connection, reset_queries as reset_sql_queries
|
44
|
+
from django.test import Client
|
45
|
+
from django.utils.encoding import force_str
|
46
|
+
from django.utils import translation
|
47
|
+
from lino.api.shell import *
|
48
|
+
from lino.core.constants import *
|
17
49
|
import os
|
18
50
|
import sys
|
19
51
|
import datetime
|
@@ -31,39 +63,11 @@ from urllib.parse import urlencode
|
|
31
63
|
import django
|
32
64
|
django.setup()
|
33
65
|
|
34
|
-
from lino.core.constants import *
|
35
|
-
from lino.api.shell import *
|
36
|
-
from django.utils import translation
|
37
|
-
from django.utils.encoding import force_str
|
38
|
-
from django.test import Client
|
39
|
-
from django.db import connection, reset_queries as reset_sql_queries
|
40
66
|
|
41
|
-
import pytest
|
42
67
|
# from rstgen import table, ul
|
43
|
-
import rstgen
|
44
|
-
from rstgen import attrtable
|
45
|
-
from rstgen.utils import unindent, rmu, sixprint
|
46
68
|
|
47
|
-
from lino.utils import AttrDict
|
48
|
-
from lino.utils import i2d
|
49
|
-
from lino.utils.html import E, tostring, to_rst
|
50
|
-
from lino.utils.diag import analyzer
|
51
|
-
from lino.utils import diag
|
52
|
-
from lino.utils.sql import sql_summary
|
53
|
-
from lino.core import actors, kernel
|
54
|
-
from lino.core import constants
|
55
|
-
from lino.core.menus import find_menu_item
|
56
|
-
from lino import logger
|
57
|
-
from lino.sphinxcontrib.actordoc import menuselection_text
|
58
|
-
from lino.utils.diag import visible_for
|
59
|
-
from lino.core.utils import full_model_name, get_models
|
60
69
|
|
61
70
|
# from lino.core.utils import PseudoRequest
|
62
|
-
from lino.utils.html import html2text
|
63
|
-
from lino.core.menus import Menu
|
64
|
-
from lino.core.actions import ShowTable
|
65
|
-
from lino.core.actions import register_params
|
66
|
-
from lino.core.layouts import BaseLayout
|
67
71
|
|
68
72
|
test_client = Client()
|
69
73
|
"""An instance of :class:`django.test.Client`.
|
@@ -275,12 +279,6 @@ def show_choices(username, url, show_count=False):
|
|
275
279
|
print("{} rows".format(result["count"]))
|
276
280
|
|
277
281
|
|
278
|
-
from django.db.models import Model
|
279
|
-
from lino.core.actions import Action
|
280
|
-
from lino.core.tables import AbstractTable
|
281
|
-
from lino.core.boundaction import BoundAction
|
282
|
-
|
283
|
-
|
284
282
|
def show_workflow(actions, all=False, language=None):
|
285
283
|
"""
|
286
284
|
Show the given actions as a table. Usage example in
|
@@ -768,7 +766,6 @@ def walk_store_fields(only_detail_fields=False):
|
|
768
766
|
yield a, sf
|
769
767
|
|
770
768
|
|
771
|
-
# settings.SITE.kernel.check_virgin()
|
772
769
|
def set_log_level(level):
|
773
770
|
logger.setLevel(level)
|
774
771
|
for handler in logger.handlers:
|
@@ -800,6 +797,7 @@ def show_change_watchers():
|
|
800
797
|
)
|
801
798
|
print(rstgen.table(headers, rows, max_width=40))
|
802
799
|
|
800
|
+
|
803
801
|
def show_display_modes():
|
804
802
|
"""
|
805
803
|
Show the availble display modes per actor.
|
@@ -813,7 +811,7 @@ def show_display_modes():
|
|
813
811
|
rows.append(
|
814
812
|
[str(a)] + [
|
815
813
|
("x" if dm in a.extra_display_modes else "")
|
816
|
-
|
814
|
+
for dm in dml]
|
817
815
|
)
|
818
816
|
print(rstgen.table(headers, rows))
|
819
817
|
|
lino/core/actions.py
CHANGED
@@ -6,6 +6,19 @@ decorator, and some of the standard actions. See :ref:`dev.actions`.
|
|
6
6
|
|
7
7
|
"""
|
8
8
|
|
9
|
+
from .utils import InstanceAction
|
10
|
+
from .utils import traverse_ddh_fklist
|
11
|
+
from .utils import Parametrizable
|
12
|
+
from .utils import navinfo
|
13
|
+
from .utils import resolve_model
|
14
|
+
from .utils import obj2unicode
|
15
|
+
from .permissions import Permittable
|
16
|
+
from lino.utils.choosers import check_for_chooser
|
17
|
+
from lino.modlib.users.utils import get_user_profile
|
18
|
+
from lino.core import keyboard
|
19
|
+
from lino.core import fields
|
20
|
+
from lino.core import layouts
|
21
|
+
from lino.core import constants
|
9
22
|
from lino import logger
|
10
23
|
|
11
24
|
from django.utils.translation import gettext_lazy as _
|
@@ -20,21 +33,6 @@ from django.apps import apps
|
|
20
33
|
|
21
34
|
get_models = apps.get_models
|
22
35
|
|
23
|
-
from lino.core import constants
|
24
|
-
from lino.core import layouts
|
25
|
-
from lino.core import fields
|
26
|
-
from lino.core import keyboard
|
27
|
-
from lino.modlib.users.utils import get_user_profile
|
28
|
-
from lino.utils.choosers import check_for_chooser
|
29
|
-
|
30
|
-
from .permissions import Permittable
|
31
|
-
from .utils import obj2unicode
|
32
|
-
from .utils import resolve_model
|
33
|
-
from .utils import navinfo
|
34
|
-
from .utils import Parametrizable
|
35
|
-
from .utils import traverse_ddh_fklist
|
36
|
-
from .utils import InstanceAction
|
37
|
-
|
38
36
|
|
39
37
|
def discover_choosers():
|
40
38
|
logger.debug("Discovering choosers for database fields...")
|
@@ -55,7 +53,8 @@ def resolve_layout(cls, k, spec, layout_class, **options):
|
|
55
53
|
else:
|
56
54
|
layout_class = settings.SITE.models.resolve(spec)
|
57
55
|
if layout_class is None:
|
58
|
-
raise Exception(
|
56
|
+
raise Exception(
|
57
|
+
"Unresolved {} {!r} for {}".format(k, spec, cls))
|
59
58
|
return layout_class(None, cls, **options)
|
60
59
|
elif isinstance(spec, layouts.Panel):
|
61
60
|
options.update(spec.options)
|
@@ -69,7 +68,8 @@ def resolve_layout(cls, k, spec, layout_class, **options):
|
|
69
68
|
"{}.{}.{} must be a string, " "a Panel or an instance of {} (not {!r})"
|
70
69
|
)
|
71
70
|
raise Exception(
|
72
|
-
msg.format(cls.__module__, cls.__name__,
|
71
|
+
msg.format(cls.__module__, cls.__name__,
|
72
|
+
k, layout_class.__name__, spec)
|
73
73
|
)
|
74
74
|
if spec._datasource is None:
|
75
75
|
spec.set_datasource(cls)
|
@@ -163,7 +163,7 @@ class Action(Parametrizable, Permittable):
|
|
163
163
|
_params_layout_class = layouts.ActionParamsLayout
|
164
164
|
|
165
165
|
label = None
|
166
|
-
button_text = None
|
166
|
+
button_text: str = None
|
167
167
|
|
168
168
|
button_color = None
|
169
169
|
"""
|
@@ -487,7 +487,8 @@ class Action(Parametrizable, Permittable):
|
|
487
487
|
|
488
488
|
if self.icon_name:
|
489
489
|
if self.icon_name not in constants.ICON_NAMES:
|
490
|
-
raise Exception(
|
490
|
+
raise Exception(
|
491
|
+
"Unkonwn icon_name '{0}'".format(self.icon_name))
|
491
492
|
|
492
493
|
register_params(self)
|
493
494
|
|
@@ -496,7 +497,6 @@ class Action(Parametrizable, Permittable):
|
|
496
497
|
if not c in constants.WINDOW_TYPES:
|
497
498
|
raise Exception(f"Invalid window_type spec {c} in {self}")
|
498
499
|
|
499
|
-
|
500
500
|
def __get__(self, instance, owner):
|
501
501
|
"""
|
502
502
|
When a model has an action "foo", then getting an attribute
|
@@ -524,7 +524,8 @@ class Action(Parametrizable, Permittable):
|
|
524
524
|
name,
|
525
525
|
getattr(
|
526
526
|
forms,
|
527
|
-
mapping.get(field.__class__.__name__,
|
527
|
+
mapping.get(field.__class__.__name__,
|
528
|
+
field.__class__.__name__),
|
528
529
|
)(),
|
529
530
|
)
|
530
531
|
return LinoForm
|
@@ -815,7 +816,7 @@ class ShowDetail(Action):
|
|
815
816
|
help_text = _("Open a detail window on this record.")
|
816
817
|
action_name = "detail"
|
817
818
|
label = _("Detail")
|
818
|
-
icon_name = "application_form"
|
819
|
+
# icon_name = "application_form"
|
819
820
|
ui5_icon_name = "sap-icon://detail-view"
|
820
821
|
opens_a_window = True
|
821
822
|
window_type = constants.WINDOW_TYPE_DETAIL
|
@@ -1415,7 +1416,8 @@ class DeleteSelected(MultipleRowAction):
|
|
1415
1416
|
d.update(type=ar.actor.model._meta.verbose_name_plural)
|
1416
1417
|
if len(objects) > 10:
|
1417
1418
|
objects = objects[:9] + ["..."]
|
1418
|
-
msg = gettext(
|
1419
|
+
msg = gettext(
|
1420
|
+
"You are about to delete %(num)d %(type)s\n(%(targets)s)") % d
|
1419
1421
|
|
1420
1422
|
if len(cascaded_objects):
|
1421
1423
|
lst = [
|
lino/core/actors.py
CHANGED
@@ -75,7 +75,8 @@ def discover():
|
|
75
75
|
actors_list = []
|
76
76
|
actors_dict = AttrDict()
|
77
77
|
|
78
|
-
logger.debug("actors.discover() : registering %d actors",
|
78
|
+
logger.debug("actors.discover() : registering %d actors",
|
79
|
+
len(actor_classes))
|
79
80
|
for cls in actor_classes:
|
80
81
|
register_actor(cls)
|
81
82
|
actor_classes = None
|
@@ -751,7 +752,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
751
752
|
if hasattr(cls, "display_mode"):
|
752
753
|
# cls.default_display_modes = {k:v for k, v in cls.display_mode}
|
753
754
|
# logger.info(f"{cls} uses deprecated `display_mode`, please convert to `default_display_modes`.")
|
754
|
-
raise ChangedAPI(
|
755
|
+
raise ChangedAPI(
|
756
|
+
f"{cls} must convert `display_mode` to `default_display_modes`")
|
755
757
|
|
756
758
|
master = getattr(cls, "master", None)
|
757
759
|
if isinstance(master, str):
|
@@ -795,6 +797,9 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
795
797
|
# cls.extra_display_modes = cls.extra_display_modes | {v}
|
796
798
|
edm.add(v)
|
797
799
|
|
800
|
+
if cls.hide_navigator:
|
801
|
+
return
|
802
|
+
|
798
803
|
if cls.card_layout is not None:
|
799
804
|
edm.add(constants.DISPLAY_MODE_CARDS)
|
800
805
|
if 'row_as_paragraph' in cls.__dict__:
|
@@ -805,7 +810,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
805
810
|
if model.extra_display_modes is not None:
|
806
811
|
for v in model.extra_display_modes:
|
807
812
|
if v not in constants.DISPLAY_MODES:
|
808
|
-
raise Exception(
|
813
|
+
raise Exception(
|
814
|
+
f"Invalid extra_display_modes mode {v} in {model}")
|
809
815
|
edm |= model.extra_display_modes
|
810
816
|
if 'as_paragraph' in model.__dict__:
|
811
817
|
edm.add(constants.DISPLAY_MODE_LIST)
|
@@ -1097,14 +1103,16 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1097
1103
|
cls.delete_action = cls._bind_action(
|
1098
1104
|
"delete_action", DELETE_ACTION, True
|
1099
1105
|
)
|
1100
|
-
cls.update_action = cls._bind_action(
|
1106
|
+
cls.update_action = cls._bind_action(
|
1107
|
+
"update_action", UPDATE_ACTION, True)
|
1101
1108
|
if cls.detail_layout:
|
1102
1109
|
cls.validate_form = cls._bind_action(
|
1103
1110
|
"validate_form", VALIDATE_FORM, True
|
1104
1111
|
)
|
1105
1112
|
|
1106
1113
|
if is_string(cls.workflow_owner_field):
|
1107
|
-
cls.workflow_owner_field = cls.get_data_elem(
|
1114
|
+
cls.workflow_owner_field = cls.get_data_elem(
|
1115
|
+
cls.workflow_owner_field)
|
1108
1116
|
if is_string(cls.workflow_state_field):
|
1109
1117
|
# if isinstance(cls.workflow_state_field, string_types):
|
1110
1118
|
fld = cls.get_data_elem(cls.workflow_state_field)
|
@@ -1136,7 +1144,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1136
1144
|
da = cls.get_default_action()
|
1137
1145
|
if da is not None:
|
1138
1146
|
if isinstance(da, actions.Action):
|
1139
|
-
cls.default_action = cls._bind_action(
|
1147
|
+
cls.default_action = cls._bind_action(
|
1148
|
+
"default_action", da, True)
|
1140
1149
|
else:
|
1141
1150
|
cls.default_action = da
|
1142
1151
|
|
@@ -1300,7 +1309,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1300
1309
|
if cls.model is None:
|
1301
1310
|
return False
|
1302
1311
|
if not isinstance(cls.model, type):
|
1303
|
-
raise Exception(
|
1312
|
+
raise Exception(
|
1313
|
+
"{}.model is {!r} (must be a class)".format(cls, cls.model))
|
1304
1314
|
return issubclass(cls.model, fields.TableRow)
|
1305
1315
|
|
1306
1316
|
@classmethod
|
@@ -1417,13 +1427,15 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1417
1427
|
return format_html("<div>{}</div>", text)
|
1418
1428
|
|
1419
1429
|
@classmethod
|
1420
|
-
def override_column_headers(self, ar, **
|
1430
|
+
def override_column_headers(self, ar, **headers):
|
1421
1431
|
"""A hook to dynamically override the column headers. This has no
|
1422
1432
|
effect on a GridPanel, only in printed documents or plain
|
1423
1433
|
html.
|
1424
1434
|
|
1425
1435
|
"""
|
1426
|
-
|
1436
|
+
if self.model is None:
|
1437
|
+
return headers
|
1438
|
+
return self.model.override_column_headers(ar, **headers)
|
1427
1439
|
|
1428
1440
|
@classmethod
|
1429
1441
|
def get_sum_text(self, ar, sums):
|
@@ -1494,11 +1506,13 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1494
1506
|
else:
|
1495
1507
|
name = "main"
|
1496
1508
|
if name in kw:
|
1497
|
-
raise Exception(
|
1509
|
+
raise Exception(
|
1510
|
+
"set_detail() got two definitions for %r." % name)
|
1498
1511
|
kw[name] = dtl
|
1499
1512
|
else:
|
1500
1513
|
if not isinstance(dtl, lcl):
|
1501
|
-
msg = "{} is neither a string nor a layout".format(
|
1514
|
+
msg = "{} is neither a string nor a layout".format(
|
1515
|
+
type(dtl))
|
1502
1516
|
raise Exception(msg)
|
1503
1517
|
assert dtl._datasource is None
|
1504
1518
|
# added for 20120914c but it wasn't the problem
|
@@ -1557,7 +1571,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1557
1571
|
# disabled because UsersWithClients defines virtual fields
|
1558
1572
|
# on connection_created
|
1559
1573
|
if name in cls.virtual_fields:
|
1560
|
-
raise Exception(
|
1574
|
+
raise Exception(
|
1575
|
+
"Duplicate add_virtual_field() %s.%s" % (cls, name))
|
1561
1576
|
# assert vf.model is None
|
1562
1577
|
# if vf.model is not None:
|
1563
1578
|
# # inherit from parent actor
|
@@ -1896,7 +1911,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1896
1911
|
@classmethod
|
1897
1912
|
def get_table_as_list(cls, obj, ar):
|
1898
1913
|
# raise Exception("20240316")
|
1899
|
-
sar = cls.request(parent=ar, master_instance=obj,
|
1914
|
+
sar = cls.request(parent=ar, master_instance=obj,
|
1915
|
+
is_on_main_actor=False)
|
1900
1916
|
grp = Grouper(sar)
|
1901
1917
|
html_text = grp.begin()
|
1902
1918
|
for i, obj in enumerate(sar.data_iterator):
|
@@ -1930,7 +1946,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1930
1946
|
|
1931
1947
|
@classmethod
|
1932
1948
|
def get_table_story(cls, obj, ar):
|
1933
|
-
sar = cls.request(parent=ar, master_instance=obj,
|
1949
|
+
sar = cls.request(parent=ar, master_instance=obj,
|
1950
|
+
is_on_main_actor=False)
|
1934
1951
|
html = SAFE_EMPTY
|
1935
1952
|
for i, obj in enumerate(sar.data_iterator):
|
1936
1953
|
if i == cls.preview_limit:
|
@@ -1956,7 +1973,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
1956
1973
|
"""
|
1957
1974
|
if ar is None:
|
1958
1975
|
return ''
|
1959
|
-
sar = cls.request(parent=ar, master_instance=obj,
|
1976
|
+
sar = cls.request(parent=ar, master_instance=obj,
|
1977
|
+
is_on_main_actor=False)
|
1960
1978
|
return cls.get_table_summary(sar)
|
1961
1979
|
|
1962
1980
|
@classmethod
|
@@ -2110,7 +2128,8 @@ def resolve_action(spec, action=None):
|
|
2110
2128
|
a = spec.get_action_by_name(action)
|
2111
2129
|
# ~ print 20121210, a
|
2112
2130
|
if a is None:
|
2113
|
-
raise Exception(
|
2131
|
+
raise Exception(
|
2132
|
+
"{} has no action named '{}'".format(spec, action))
|
2114
2133
|
else:
|
2115
2134
|
a = spec.default_action
|
2116
2135
|
# assert a is not None
|
@@ -2118,4 +2137,5 @@ def resolve_action(spec, action=None):
|
|
2118
2137
|
raise Exception("%r default_action is None?!" % spec)
|
2119
2138
|
return a
|
2120
2139
|
|
2121
|
-
raise Exception("Action spec %r returned invalid object %r" %
|
2140
|
+
raise Exception("Action spec %r returned invalid object %r" %
|
2141
|
+
(givenspec, spec))
|
lino/core/choicelists.py
CHANGED
@@ -36,9 +36,10 @@ VALUE_FIELD.attname = "value"
|
|
36
36
|
|
37
37
|
# @deconstructible
|
38
38
|
class Choice(fields.TableRow):
|
39
|
-
"""
|
40
|
-
|
41
|
-
|
39
|
+
"""
|
40
|
+
A constant value whose string representation depends on the current language
|
41
|
+
at runtime. Every item of a :class:`ChoiceList` must be an instance of
|
42
|
+
:class:`Choice` or a subclass thereof.
|
42
43
|
|
43
44
|
.. attribute:: choicelist
|
44
45
|
|
@@ -478,11 +479,11 @@ class ChoiceList(with_metaclass(ChoiceListMeta, tables.AbstractTable)):
|
|
478
479
|
|
479
480
|
old2new = {}
|
480
481
|
"""
|
481
|
-
A dict
|
482
|
+
A dict that maps old values to their new values.
|
482
483
|
|
483
|
-
This
|
484
|
-
|
485
|
-
|
484
|
+
This is consulted when an unknown value is read from database (e.g. during a
|
485
|
+
migration). If it contains a replacement for the old value, Lino will
|
486
|
+
return the choice with the new value.
|
486
487
|
"""
|
487
488
|
|
488
489
|
@classmethod
|
@@ -1050,7 +1051,8 @@ class MultiChoiceListField(ChoiceListField):
|
|
1050
1051
|
return []
|
1051
1052
|
if isinstance(value, list):
|
1052
1053
|
return value
|
1053
|
-
value = [self.choicelist.to_python(
|
1054
|
+
value = [self.choicelist.to_python(
|
1055
|
+
v) for v in value.split(self.delimiter_char)]
|
1054
1056
|
return value
|
1055
1057
|
|
1056
1058
|
def get_prep_value(self, value):
|
lino/core/dbtables.py
CHANGED
@@ -266,7 +266,7 @@ class Table(AbstractTable):
|
|
266
266
|
yield self.detail_action.request(user=user)
|
267
267
|
|
268
268
|
# @classmethod
|
269
|
-
# def
|
269
|
+
# def elem_get_printable_target_stem(cls,elem):
|
270
270
|
# return elem._meta.app_label + '.' + elem.__class__.__name__ + '-' + str(elem.pk)
|
271
271
|
@classmethod
|
272
272
|
def get_detail_sets(self):
|