lino 25.5.1__py3-none-any.whl → 25.5.3__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 +5 -3
- lino/api/doctest.py +2 -2
- lino/core/__init__.py +3 -3
- lino/core/actions.py +60 -582
- lino/core/actors.py +66 -32
- lino/core/atomizer.py +355 -0
- lino/core/boundaction.py +8 -4
- lino/core/constants.py +3 -1
- lino/core/dbtables.py +4 -3
- lino/core/elems.py +33 -21
- lino/core/fields.py +40 -210
- lino/core/kernel.py +18 -13
- lino/core/layouts.py +30 -57
- lino/core/model.py +6 -4
- lino/core/permissions.py +18 -0
- lino/core/renderer.py +5 -1
- lino/core/requests.py +13 -7
- lino/core/signals.py +1 -1
- lino/core/site.py +7 -8
- lino/core/store.py +13 -156
- lino/core/tables.py +10 -1
- lino/core/utils.py +124 -1
- lino/locale/bn/LC_MESSAGES/django.po +1034 -868
- lino/locale/de/LC_MESSAGES/django.mo +0 -0
- lino/locale/de/LC_MESSAGES/django.po +996 -892
- lino/locale/django.pot +968 -869
- lino/locale/es/LC_MESSAGES/django.po +1032 -869
- lino/locale/et/LC_MESSAGES/django.po +1032 -866
- lino/locale/fr/LC_MESSAGES/django.po +1034 -866
- lino/locale/nl/LC_MESSAGES/django.po +1040 -868
- lino/locale/pt_BR/LC_MESSAGES/django.po +1029 -868
- lino/locale/zh_Hant/LC_MESSAGES/django.po +1029 -868
- lino/mixins/duplicable.py +8 -2
- lino/mixins/registrable.py +1 -1
- lino/modlib/changes/utils.py +4 -3
- lino/modlib/export_excel/models.py +7 -3
- lino/modlib/extjs/ext_renderer.py +1 -1
- lino/modlib/extjs/views.py +5 -0
- lino/modlib/linod/mixins.py +10 -11
- lino/modlib/memo/mixins.py +1 -3
- lino/modlib/summaries/__init__.py +2 -2
- lino/modlib/uploads/ui.py +6 -8
- lino/modlib/users/fixtures/demo_users.py +16 -13
- lino/utils/choosers.py +11 -1
- lino/utils/diag.py +6 -4
- lino/utils/fieldutils.py +14 -11
- lino/utils/instantiator.py +4 -2
- lino/utils/report.py +5 -3
- {lino-25.5.1.dist-info → lino-25.5.3.dist-info}/METADATA +1 -1
- {lino-25.5.1.dist-info → lino-25.5.3.dist-info}/RECORD +54 -53
- {lino-25.5.1.dist-info → lino-25.5.3.dist-info}/WHEEL +0 -0
- {lino-25.5.1.dist-info → lino-25.5.3.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.5.1.dist-info → lino-25.5.3.dist-info}/licenses/COPYING +0 -0
lino/core/utils.py
CHANGED
@@ -640,7 +640,7 @@ def navinfo(qs, elem, limit=None):
|
|
640
640
|
)
|
641
641
|
|
642
642
|
|
643
|
-
class Parametrizable
|
643
|
+
class Parametrizable:
|
644
644
|
"""
|
645
645
|
Base class for both Actors and Actions. See :doc:`/dev/parameters`.
|
646
646
|
|
@@ -1129,3 +1129,126 @@ def show(*args, **kwargs):
|
|
1129
1129
|
def shows(*args, **kwargs):
|
1130
1130
|
"""Return the output of :func:`show`."""
|
1131
1131
|
return capture_output(show, *args, **kwargs)
|
1132
|
+
|
1133
|
+
|
1134
|
+
class Panel:
|
1135
|
+
"""
|
1136
|
+
To be used when a panel cannot be expressed using a simple
|
1137
|
+
template string because it requires one or more options. These
|
1138
|
+
`options` parameters can be:
|
1139
|
+
|
1140
|
+
- label
|
1141
|
+
- required_roles
|
1142
|
+
- window_size
|
1143
|
+
- label_align
|
1144
|
+
|
1145
|
+
Unlike a :class:`BaseLayout` it cannot have any child panels
|
1146
|
+
and cannot become a tabbed panel.
|
1147
|
+
"""
|
1148
|
+
|
1149
|
+
def __init__(self, desc, label=None, **options):
|
1150
|
+
# assert not 'required' in options
|
1151
|
+
self.desc = desc
|
1152
|
+
if label is not None:
|
1153
|
+
options.update(label=label)
|
1154
|
+
self.options = options
|
1155
|
+
|
1156
|
+
def replace(self, *args, **kw):
|
1157
|
+
"""
|
1158
|
+
Calls the standard :meth:`string.replace`
|
1159
|
+
method on this Panel's template.
|
1160
|
+
"""
|
1161
|
+
self.desc = self.desc.replace(*args, **kw)
|
1162
|
+
|
1163
|
+
|
1164
|
+
def resolve_layout(cls, k, spec, layout_class, **options):
|
1165
|
+
# k: just for naming the culprit in error messages
|
1166
|
+
if isinstance(spec, str):
|
1167
|
+
if "\n" in spec or "." not in spec:
|
1168
|
+
return layout_class(spec, cls, **options)
|
1169
|
+
else:
|
1170
|
+
layout_class = settings.SITE.models.resolve(spec)
|
1171
|
+
if layout_class is None:
|
1172
|
+
raise Exception(
|
1173
|
+
"Unresolved {} {!r} for {}".format(k, spec, cls))
|
1174
|
+
return layout_class(None, cls, **options)
|
1175
|
+
elif isinstance(spec, Panel):
|
1176
|
+
options.update(spec.options)
|
1177
|
+
return layout_class(spec.desc, cls, **options)
|
1178
|
+
else:
|
1179
|
+
if not isinstance(spec, layout_class):
|
1180
|
+
if not isinstance(cls, type):
|
1181
|
+
# cls is an action instance
|
1182
|
+
cls = cls.__class__
|
1183
|
+
msg = (
|
1184
|
+
"{}.{}.{} must be a string, " "a Panel or an instance of {} (not {!r})"
|
1185
|
+
)
|
1186
|
+
raise Exception(
|
1187
|
+
msg.format(cls.__module__, cls.__name__,
|
1188
|
+
k, layout_class.__name__, spec)
|
1189
|
+
)
|
1190
|
+
if spec._datasource is None:
|
1191
|
+
spec.set_datasource(cls)
|
1192
|
+
return spec
|
1193
|
+
elif not issubclass(cls, spec._datasource):
|
1194
|
+
raise Exception(
|
1195
|
+
"Cannot reuse %s instance (%s of %r) for %r"
|
1196
|
+
% (spec.__class__, k, spec._datasource, cls)
|
1197
|
+
)
|
1198
|
+
return spec
|
1199
|
+
|
1200
|
+
|
1201
|
+
def install_layout(cls, k, layout_class, **options):
|
1202
|
+
"""
|
1203
|
+
- `cls` is the actor (a class object)
|
1204
|
+
|
1205
|
+
- `k` is one of 'grid_layout', 'detail_layout', 'insert_layout',
|
1206
|
+
'params_layout', 'card_layout'
|
1207
|
+
|
1208
|
+
- `layout_class`
|
1209
|
+
|
1210
|
+
"""
|
1211
|
+
# if str(cls) == 'courses.Pupils':
|
1212
|
+
# print("20160329 install_layout", k, layout_class)
|
1213
|
+
dl = cls.__dict__.get(k, None)
|
1214
|
+
if dl is None: # and not cls._class_init_done:
|
1215
|
+
dl = getattr(cls, k, None)
|
1216
|
+
if dl is None:
|
1217
|
+
return
|
1218
|
+
setattr(cls, k, resolve_layout(cls, k, dl, layout_class, **options))
|
1219
|
+
|
1220
|
+
|
1221
|
+
def register_params(cls):
|
1222
|
+
"""`cls` is either an actor (a class object) or an action (an
|
1223
|
+
instance).
|
1224
|
+
|
1225
|
+
"""
|
1226
|
+
if cls.parameters is not None:
|
1227
|
+
for k, v in cls.parameters.items():
|
1228
|
+
v.set_attributes_from_name(k)
|
1229
|
+
v.table = cls
|
1230
|
+
# v.model = cls # 20181023 experimentally
|
1231
|
+
|
1232
|
+
if cls.params_layout is None:
|
1233
|
+
if cls._params_layout_class is None:
|
1234
|
+
raise Exception(f"{cls} has no _params_layout_class")
|
1235
|
+
cls.params_layout = cls._params_layout_class.join_str.join(
|
1236
|
+
cls.parameters.keys()
|
1237
|
+
)
|
1238
|
+
install_layout(cls, "params_layout", cls._params_layout_class)
|
1239
|
+
|
1240
|
+
# e.g. accounting.ByJournal is just a mixin but provides a default value for its children
|
1241
|
+
elif cls.params_layout is not None:
|
1242
|
+
raise Exception("{} has a params_layout but no parameters".format(cls))
|
1243
|
+
|
1244
|
+
# if isinstance(cls, type) and cls.__name__.endswith("Users"):
|
1245
|
+
# # if isinstance(cls, type) and cls.model is not None and cls.model.__name__ == "User":
|
1246
|
+
# # if str(cls.model) != "users.User":
|
1247
|
+
# # raise Exception("{} {}".format(cls, cls.model))
|
1248
|
+
# print("20200825 {}.register_params {} {}".format(
|
1249
|
+
# cls, cls.parameters, cls.params_layout))
|
1250
|
+
|
1251
|
+
|
1252
|
+
def make_params_layout_handle(self):
|
1253
|
+
# `self` is either an Action instance or an Actor class object
|
1254
|
+
return self.params_layout.get_layout_handle()
|