lino 25.5.2__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.
Files changed (51) hide show
  1. lino/__init__.py +1 -1
  2. lino/api/dd.py +5 -3
  3. lino/api/doctest.py +2 -2
  4. lino/core/__init__.py +3 -3
  5. lino/core/actions.py +60 -582
  6. lino/core/actors.py +66 -32
  7. lino/core/atomizer.py +355 -0
  8. lino/core/boundaction.py +8 -4
  9. lino/core/constants.py +3 -1
  10. lino/core/dbtables.py +4 -3
  11. lino/core/elems.py +33 -21
  12. lino/core/fields.py +40 -210
  13. lino/core/kernel.py +18 -13
  14. lino/core/layouts.py +30 -57
  15. lino/core/model.py +6 -4
  16. lino/core/permissions.py +18 -0
  17. lino/core/renderer.py +5 -1
  18. lino/core/requests.py +13 -7
  19. lino/core/signals.py +1 -1
  20. lino/core/site.py +1 -1
  21. lino/core/store.py +13 -156
  22. lino/core/tables.py +5 -2
  23. lino/core/utils.py +124 -1
  24. lino/locale/bn/LC_MESSAGES/django.po +1034 -868
  25. lino/locale/de/LC_MESSAGES/django.mo +0 -0
  26. lino/locale/de/LC_MESSAGES/django.po +996 -892
  27. lino/locale/django.pot +968 -869
  28. lino/locale/es/LC_MESSAGES/django.po +1032 -869
  29. lino/locale/et/LC_MESSAGES/django.po +1032 -866
  30. lino/locale/fr/LC_MESSAGES/django.po +1034 -866
  31. lino/locale/nl/LC_MESSAGES/django.po +1040 -868
  32. lino/locale/pt_BR/LC_MESSAGES/django.po +1029 -868
  33. lino/locale/zh_Hant/LC_MESSAGES/django.po +1029 -868
  34. lino/mixins/duplicable.py +8 -2
  35. lino/mixins/registrable.py +1 -1
  36. lino/modlib/changes/utils.py +4 -3
  37. lino/modlib/extjs/ext_renderer.py +1 -1
  38. lino/modlib/extjs/views.py +5 -0
  39. lino/modlib/memo/mixins.py +1 -3
  40. lino/modlib/uploads/ui.py +6 -8
  41. lino/modlib/users/fixtures/demo_users.py +16 -13
  42. lino/utils/choosers.py +11 -1
  43. lino/utils/diag.py +6 -4
  44. lino/utils/fieldutils.py +14 -11
  45. lino/utils/instantiator.py +4 -2
  46. lino/utils/report.py +5 -3
  47. {lino-25.5.2.dist-info → lino-25.5.3.dist-info}/METADATA +1 -1
  48. {lino-25.5.2.dist-info → lino-25.5.3.dist-info}/RECORD +51 -50
  49. {lino-25.5.2.dist-info → lino-25.5.3.dist-info}/WHEEL +0 -0
  50. {lino-25.5.2.dist-info → lino-25.5.3.dist-info}/licenses/AUTHORS.rst +0 -0
  51. {lino-25.5.2.dist-info → lino-25.5.3.dist-info}/licenses/COPYING +0 -0
lino/core/elems.py CHANGED
@@ -32,10 +32,11 @@ from lino import logger
32
32
 
33
33
  from lino.core import layouts
34
34
  from lino.core import fields
35
- from lino.core.actions import Action, Permittable
36
35
  from lino.core import constants
37
- from lino.core.gfks import GenericRelation, GenericRel
38
36
  from lino.core import choicelists
37
+ from lino.core import actions
38
+ from lino.core.gfks import GenericRelation, GenericRel
39
+ from lino.core.permissions import Permittable
39
40
  from lino.modlib.bootstrap3.views import table2html
40
41
 
41
42
  from lino.utils.jsgen import VisibleComponent
@@ -50,12 +51,10 @@ from lino.core.actors import qs2summary
50
51
 
51
52
  from lino.core.layouts import (
52
53
  FormLayout,
53
- ParamsLayout,
54
54
  ColumnsLayout,
55
- ActionParamsLayout,
56
55
  DummyPanel,
57
56
  )
58
-
57
+ from lino.core.layouts import ParamsLayout, ActionParamsLayout
59
58
  from lino.utils.mldbc.fields import BabelCharField, BabelTextField
60
59
  from lino.core import tables
61
60
  from lino.core.gfks import GenericForeignKey
@@ -1801,13 +1800,12 @@ class LightWeightContainer(HtmlBoxElement):
1801
1800
 
1802
1801
  """
1803
1802
 
1804
- def __init__(self, lh, slave, name, return_type, **kwargs):
1803
+ def __init__(self, lh, slave, name, meth, **kwargs):
1805
1804
  box = fields.HtmlBox(
1806
- slave.label, name=name, help_text=slave.help_text, delayed_value=True
1805
+ slave.get_label(), name=name, help_text=slave.help_text, delayed_value=True
1807
1806
  )
1808
-
1809
- box._return_type_for_method = return_type
1810
- fld = fields.VirtualField(box, return_type)
1807
+ box._return_type_for_method = meth
1808
+ fld = fields.VirtualField(box, meth, verbose_name=slave.get_label())
1811
1809
  # self.value = dict(value=dict(data="")) # compare react.views.DelayedValue
1812
1810
  # self.value = dict(data="") # compare react.views.DelayedValue
1813
1811
  # assert box.delayed_value == True
@@ -1844,7 +1842,6 @@ class SlaveSummaryPanel(LightWeightContainer):
1844
1842
 
1845
1843
  class StoryElement(LightWeightContainer):
1846
1844
  """
1847
-
1848
1845
  The panel used to display objects as plain html generated by
1849
1846
  :meth:`as_summary_row <lino.core.fields.TableRow.as_summary_row>` when
1850
1847
  `display_mode` is `DISPLAY_MODE_STORY`.
@@ -1860,6 +1857,11 @@ class ListElement(LightWeightContainer):
1860
1857
  super().__init__(lh, slave, name, slave.get_table_as_list, **kw)
1861
1858
 
1862
1859
 
1860
+ class TilesElement(LightWeightContainer):
1861
+ def __init__(self, lh, slave, name, **kw):
1862
+ super().__init__(lh, slave, name, slave.get_table_as_tiles, **kw)
1863
+
1864
+
1863
1865
  class ManyRelatedObjectElement(HtmlBoxElement):
1864
1866
  def __init__(self, lh, relobj, **kw):
1865
1867
  name = relobj.field.remote_field.related_name
@@ -2448,6 +2450,8 @@ class SlaveContainer(GridElement):
2448
2450
  slaves = dict()
2449
2451
  if constants.DISPLAY_MODE_STORY in rpt.extra_display_modes:
2450
2452
  slaves["story"] = get_story_element(layout_handle, rpt, name, **kw)
2453
+ if constants.DISPLAY_MODE_TILES in rpt.extra_display_modes:
2454
+ slaves["tiles"] = get_tiles_element(layout_handle, rpt, name, **kw)
2451
2455
  if constants.DISPLAY_MODE_LIST in rpt.extra_display_modes:
2452
2456
  slaves["list"] = get_list_element(layout_handle, rpt, name, **kw)
2453
2457
  if constants.DISPLAY_MODE_SUMMARY in rpt.extra_display_modes:
@@ -2721,18 +2725,23 @@ def create_layout_panel(lh, name, vertical, elems, **kwargs):
2721
2725
  return Panel(lh, name, vertical, *elems, **pkw)
2722
2726
 
2723
2727
 
2724
- def get_story_element(lh, de, name, **kw):
2725
- e = StoryElement(lh, de, name, **kw)
2728
+ def get_display_element(lh, de, name, cls, **kwargs):
2729
+ e = cls(lh, de, name, **kwargs)
2726
2730
  e.add_requirements(*de.required_roles)
2727
2731
  lh.add_data_elem(e.field)
2728
2732
  return e
2729
2733
 
2730
2734
 
2735
+ def get_story_element(lh, de, name, **kw):
2736
+ return get_display_element(lh, de, name, StoryElement, **kw)
2737
+
2738
+
2739
+ def get_tiles_element(lh, de, name, **kw):
2740
+ return get_display_element(lh, de, name, TilesElement, **kw)
2741
+
2742
+
2731
2743
  def get_list_element(lh, de, name, **kw):
2732
- e = ListElement(lh, de, name, **kw)
2733
- e.add_requirements(*de.required_roles)
2734
- lh.add_data_elem(e.field)
2735
- return e
2744
+ return get_display_element(lh, de, name, ListElement, **kw)
2736
2745
 
2737
2746
 
2738
2747
  def get_htmlbox_element(lh, de, name, **kw):
@@ -2908,15 +2917,18 @@ def create_layout_element(lh, name, **kw):
2908
2917
  elif dm == constants.DISPLAY_MODE_HTML:
2909
2918
  return get_htmlbox_element(lh, de, name, **kw)
2910
2919
 
2911
- elif dm == constants.DISPLAY_MODE_STORY:
2912
- return get_story_element(lh, de, name, **kw)
2913
-
2914
2920
  elif dm == constants.DISPLAY_MODE_SUMMARY:
2915
2921
  return get_summary_element(lh, de, name, **kw)
2916
2922
 
2917
2923
  elif dm == constants.DISPLAY_MODE_LIST:
2918
2924
  return get_list_element(lh, de, name, **kw)
2919
2925
 
2926
+ elif dm == constants.DISPLAY_MODE_STORY:
2927
+ return get_story_element(lh, de, name, **kw)
2928
+
2929
+ elif dm == constants.DISPLAY_MODE_TILES:
2930
+ return get_tiles_element(lh, de, name, **kw)
2931
+
2920
2932
  # elif dm == 'reactive': # TODO: is this still being used?
2921
2933
  # e = ReactiveElement(lh, de, **kw)
2922
2934
  # e.add_requirements(*de.required_roles)
@@ -2932,7 +2944,7 @@ def create_layout_element(lh, name, **kw):
2932
2944
  # lh.add_data_elem(e.field)
2933
2945
  # return e
2934
2946
 
2935
- if isinstance(de, Action):
2947
+ if isinstance(de, actions.Action):
2936
2948
  return ButtonElement(lh, name, de)
2937
2949
 
2938
2950
  if isinstance(de, fields.VirtualField):
lino/core/fields.py CHANGED
@@ -33,13 +33,15 @@ from lino.core.utils import (
33
33
  from lino.core.exceptions import ChangedAPI
34
34
  from lino.core.diff import ChangeWatcher
35
35
  from lino.core import constants
36
+ from lino.core import atomizer
36
37
 
37
38
  from lino.utils import isiterable
38
- from lino.utils import get_class_attr
39
+ from lino.utils import choosers
40
+ # from lino.utils import get_class_attr
39
41
  from lino.utils import IncompleteDate
40
42
  from lino.utils import quantities
41
43
  from lino.utils.quantities import Duration
42
- from lino.modlib.gfks.fields import GenericForeignKeyIdField
44
+ # from lino.modlib.gfks.fields import GenericForeignKeyIdField
43
45
 
44
46
  from .signals import pre_ui_save
45
47
 
@@ -369,8 +371,9 @@ class RemoteField(FakeField):
369
371
  """
370
372
  A field on a related object.
371
373
 
372
- Remote fields are created by
373
- :meth:`lino.core.model.Model.get_data_elem` when needed.
374
+ Remote fields are created by :func:`lino.core.atomizer.create_atomizer`
375
+ (which itself is called by :meth:`lino.core.model.Model.get_data_elem`) when
376
+ needed.
374
377
 
375
378
  .. attribute:: field
376
379
 
@@ -382,6 +385,7 @@ class RemoteField(FakeField):
382
385
  # ~ editable = False
383
386
 
384
387
  def __init__(self, getter, name, fld, setter=None, **kwargs):
388
+ # from lino.core import choicelists
385
389
  self.func = getter
386
390
  self.name = name
387
391
  self.attname = name
@@ -405,7 +409,7 @@ class RemoteField(FakeField):
405
409
  if setter is not None:
406
410
  self.editable = True
407
411
  self.choices = getattr(fld, "choices", None)
408
- super(RemoteField, self).__init__(**kwargs)
412
+ super().__init__(**kwargs)
409
413
  # ~ print 20120424, self.name
410
414
  # ~ settings.SITE.register_virtual_field(self)
411
415
 
@@ -417,6 +421,9 @@ class RemoteField(FakeField):
417
421
  ):
418
422
  fld.lino_resolve_type() # 20200425
419
423
  fk = fld.return_type
424
+ # elif isinstance(fld, choicelists.ChoiceListField):
425
+ # self.choicelist = fld.choicelist
426
+ # fk = None
420
427
  elif isinstance(fld, models.ForeignKey):
421
428
  fk = fld
422
429
  else:
@@ -425,9 +432,7 @@ class RemoteField(FakeField):
425
432
  # if not fk.remote_field:
426
433
  # raise Exception("20200425 {} has no remote_field".format(fk))
427
434
  self.remote_field = fk.remote_field
428
- from lino.core import store
429
-
430
- store.get_atomizer(self.remote_field, self, name)
435
+ atomizer.get_atomizer(self.remote_field, self, name)
431
436
 
432
437
  def __str__(self):
433
438
  # return "<RemoteField({})>".format(self.name)
@@ -539,12 +544,12 @@ class VirtualModel:
539
544
  self._meta = model._meta
540
545
 
541
546
 
542
- VFIELD_ATTRIBS = frozenset(
543
- """to_python choices save_form_data
544
- value_to_string max_length remote_field
545
- max_digits verbose_name decimal_places wildcard_data_elem
546
- blank choices""".split()
547
- )
547
+ VFIELD_ATTRIBS = frozenset([
548
+ "to_python", "choices", "save_form_data",
549
+ "value_to_string", "max_length", "remote_field",
550
+ "max_digits", "verbose_name", "decimal_places",
551
+ "wildcard_data_elem", "blank"
552
+ ])
548
553
 
549
554
 
550
555
  def return_none(obj, ar):
@@ -657,9 +662,10 @@ class VirtualField(FakeField):
657
662
  # logger.info('20170905 resolve_type done %s %s',
658
663
  # self.name, self.verbose_name)
659
664
 
660
- from lino.core import store
665
+ # if self.name is None or self.model is None:
666
+ # return
661
667
 
662
- store.get_atomizer(self.model, self, self.name)
668
+ atomizer.get_atomizer(self.model, self, self.name)
663
669
 
664
670
  # print("20181023 Done: lino_resolve_type() for {}".format(self))
665
671
 
@@ -1247,7 +1253,7 @@ class ImportedFields(object):
1247
1253
  @classmethod
1248
1254
  def declare_imported_fields(cls, names):
1249
1255
  cls._imported_fields = cls._imported_fields | set(
1250
- fields_list(cls, names))
1256
+ atomizer.fields_list(cls, names))
1251
1257
  # ~ logger.info('20120801 %s.declare_imported_fields() --> %s' % (
1252
1258
  # ~ cls,cls._imported_fields))
1253
1259
 
@@ -1277,7 +1283,7 @@ class TableRow(object):
1277
1283
  def get_chooser_for_field(cls, fieldname):
1278
1284
  d = getattr(cls, "_choosers_dict", {})
1279
1285
  # if fieldname.endswith("__municipality"):
1280
- # print("20200425 Model.get_chooser_for_field", cls, fieldname, d)
1286
+ # print("20200425 Model.get_chooser_for_field", cls, fieldname, d)
1281
1287
  return d.get(fieldname, None)
1282
1288
 
1283
1289
  @classmethod
@@ -1457,6 +1463,9 @@ class TableRow(object):
1457
1463
  return escape(str(self))
1458
1464
  return tostring(self.as_summary_item(ar, **kwargs))
1459
1465
 
1466
+ def as_tile(self, ar, **kwargs):
1467
+ return self.as_paragraph(ar, **kwargs)
1468
+
1460
1469
  def as_story_item(self, ar, **kwargs):
1461
1470
  kwargs.update(display_mode=constants.DISPLAY_MODE_STORY)
1462
1471
  return mark_safe("".join(self.as_page(ar, **kwargs)))
@@ -1533,57 +1542,6 @@ def use_as_wildcard(de):
1533
1542
  return True
1534
1543
 
1535
1544
 
1536
- def fields_list(model, field_names):
1537
- """
1538
- Return a set with the names of the specified fields, checking
1539
- whether each of them exists.
1540
-
1541
- Arguments: `model` is any subclass of `django.db.models.Model`. It
1542
- may be a string with the full name of a model
1543
- (e.g. ``"myapp.MyModel"``). `field_names` is a single string with
1544
- a space-separated list of field names.
1545
-
1546
- If one of the names refers to a dummy field, this name will be ignored
1547
- silently.
1548
-
1549
- For example if you have a model `MyModel` with two fields `foo` and
1550
- `bar`, then ``dd.fields_list(MyModel,"foo bar")`` will return
1551
- ``['foo','bar']`` and ``dd.fields_list(MyModel,"foo baz")`` will raise
1552
- an exception.
1553
-
1554
- TODO: either rename this to `fields_set` or change it to return an
1555
- iterable on the fields.
1556
- """
1557
- lst = set()
1558
- names_list = field_names.split()
1559
-
1560
- for name in names_list:
1561
- if name == "*":
1562
- explicit_names = set()
1563
- for name in names_list:
1564
- if name != "*":
1565
- explicit_names.add(name)
1566
- for de in wildcard_data_elems(model):
1567
- if not isinstance(de, DummyField):
1568
- if de.name not in explicit_names:
1569
- if use_as_wildcard(de):
1570
- lst.add(de.name)
1571
- else:
1572
- e = model.get_data_elem(name)
1573
- if e is None:
1574
- raise FieldDoesNotExist(
1575
- "No data element %r in %s" % (name, model))
1576
- if not hasattr(e, "name"):
1577
- raise FieldDoesNotExist(
1578
- "%s %r in %s has no name" % (e.__class__, name, model)
1579
- )
1580
- if isinstance(e, DummyField):
1581
- pass
1582
- else:
1583
- lst.add(e.name)
1584
- return lst
1585
-
1586
-
1587
1545
  def pointer_factory(cls, othermodel, *args, **kw):
1588
1546
  """
1589
1547
  Instantiate a `ForeignKey` or `OneToOneField` with some subtle
@@ -1610,147 +1568,6 @@ def pointer_factory(cls, othermodel, *args, **kw):
1610
1568
  return cls(othermodel, *args, **kw)
1611
1569
 
1612
1570
 
1613
- def make_remote_field(model, name):
1614
- from lino.utils import choosers
1615
- parts = name.split("__")
1616
- if len(parts) == 1:
1617
- return
1618
- # It's going to be a RemoteField
1619
- # logger.warning("20151203 RemoteField %s in %s", name, cls)
1620
-
1621
- from lino.core import store
1622
-
1623
- cls = model
1624
- field_chain = []
1625
- editable = False
1626
- gettable = True
1627
- leaf_chooser = None
1628
- for n in parts:
1629
- if model is None:
1630
- return
1631
- # raise Exception(
1632
- # "Invalid remote field {0} for {1}".format(name, cls))
1633
-
1634
- if isinstance(model, str):
1635
- # Django 1.9 no longer resolves the
1636
- # rel.model of ForeignKeys on abstract
1637
- # models, so we do it here.
1638
- model = resolve_model(model)
1639
- # logger.warning("20151203 %s", model)
1640
-
1641
- fld = model.get_data_elem(n)
1642
- if fld is None:
1643
- return
1644
- # raise Exception(
1645
- # "Invalid RemoteField %s.%s (no field %s in %s)" %
1646
- # (full_model_name(model), name, n, full_model_name(model)))
1647
-
1648
- if isinstance(fld, DummyField):
1649
- # a remote field containing at least one dummy field is itself a
1650
- # dummy field
1651
- return fld
1652
-
1653
- # Why was this? it caused docs/specs/avanti/courses.rst to fail
1654
- # if isinstance(fld, models.ManyToOneRel):
1655
- # gettable = False
1656
-
1657
- # make sure that the atomizer gets created.
1658
- store.get_atomizer(model, fld, fld.name)
1659
-
1660
- if isinstance(fld, VirtualField):
1661
- fld.lino_resolve_type()
1662
- leaf_chooser = choosers.check_for_chooser(model, fld)
1663
-
1664
- field_chain.append(fld)
1665
- if isinstance(
1666
- fld, (models.OneToOneRel, models.OneToOneField, models.ForeignKey)
1667
- ):
1668
- editable = True
1669
- if getattr(fld, "remote_field", None):
1670
- model = fld.remote_field.model
1671
- else:
1672
- model = None
1673
-
1674
- # if not gettable:
1675
- # # raise Exception("20231112")
1676
- # return RemoteField(none_getter, name, fld)
1677
-
1678
- if leaf_chooser is not None:
1679
- d = choosers.get_choosers_dict(cls)
1680
- d[name] = leaf_chooser
1681
-
1682
- def getter(obj, ar=None):
1683
- try:
1684
- for fld in field_chain:
1685
- if obj is None:
1686
- return None
1687
- obj = fld._lino_atomizer.full_value_from_object(obj, ar)
1688
- return obj
1689
- except Exception as e:
1690
- # raise
1691
- msg = "Error while computing {}: {} ({} in {})"
1692
- raise Exception(msg.format(name, e, fld, field_chain))
1693
- # ~ if False: # only for debugging
1694
- if True: # see 20130802
1695
- logger.exception(e)
1696
- return str(e)
1697
- return None
1698
-
1699
- if not editable:
1700
- rf = RemoteField(getter, name, fld)
1701
- # choosers.check_for_chooser(model, rf)
1702
- return rf
1703
-
1704
- def setter(obj, value):
1705
- # logger.info("20180712 %s setter() %s", name, value)
1706
- # all intermediate fields are OneToOneRel
1707
- target = obj
1708
- try:
1709
- for i, fld in enumerate(field_chain):
1710
- # print("20180712a %s" % fld)
1711
- if isinstance(fld, (models.OneToOneRel, models.ForeignKey)):
1712
- reltarget = getattr(target, fld.name, None)
1713
- if reltarget is None:
1714
- rkw = {fld.field.name: target}
1715
- # print(
1716
- # "20180712 create {}({})".format(
1717
- # fld.related_model, rkw))
1718
- reltarget = fld.related_model(**rkw)
1719
- reltarget.save_new_instance(
1720
- fld.related_model.get_default_table().create_request()
1721
- )
1722
-
1723
- setattr(target, fld.name, reltarget)
1724
-
1725
- if target == obj and target.id is None:
1726
- # Model.save_new_instance will be called do not insert this record.
1727
- target = reltarget
1728
- continue
1729
- target.full_clean()
1730
- target.save()
1731
- # print("20180712b {}.{} = {}".format(
1732
- # target, fld.name, reltarget))
1733
- target = reltarget
1734
- else:
1735
- setattr(target, fld.name, value)
1736
- target.full_clean()
1737
- target.save()
1738
- # print(
1739
- # "20180712c setattr({},{},{}".format(
1740
- # target, fld.name, value))
1741
- return True
1742
- except Exception as e:
1743
- if False: # only for debugging
1744
- logger.exception(e)
1745
- return str(e)
1746
- raise e.__class__("Error while setting %s: %s" % (name, e))
1747
- return False
1748
-
1749
- rf = RemoteField(getter, name, fld, setter)
1750
- # choosers.check_for_chooser(model, rf)
1751
- return rf
1752
-
1753
-
1754
1571
  # # would be nice for lino_xl.lib.vat.VatItemBase.item_total
1755
1572
  # class FieldAlias(VirtualField):
1756
1573
  # def __init__(self, orig_name):
@@ -1852,3 +1669,16 @@ def choices_for_field(ar, holder, field):
1852
1669
  else:
1853
1670
  raise http.Http404("No choices for %s" % field)
1854
1671
  return (qs, row2dict)
1672
+
1673
+
1674
+ def setup_params_choosers(self):
1675
+ if self.parameters:
1676
+ for k, fld in self.parameters.items():
1677
+ if isinstance(fld, models.ForeignKey):
1678
+ msg = "Invalid target %s in parameter {} of {}".format(k, self)
1679
+ fld.remote_field.model = resolve_model(
1680
+ fld.remote_field.model, strict=msg
1681
+ )
1682
+ set_default_verbose_name(fld)
1683
+
1684
+ choosers.check_for_chooser(self, fld)
lino/core/kernel.py CHANGED
@@ -50,22 +50,22 @@ from lino.utils.html import E
50
50
  # from lino.utils import isiterable
51
51
  from lino.core import layouts
52
52
  from lino.core import actors
53
- from lino.core import actions
54
53
  from lino.core import frames
55
- from lino.core import fields
56
54
  from lino.core import dbtables
55
+ from lino.core import atomizer
57
56
  from lino.core import choicelists
58
57
  from lino.core import workflows
59
58
  from lino.core import tables
60
59
  from lino.core import constants
61
60
  from lino.core.model import Model
62
- from lino.core.roles import UserRole
61
+ # from lino.core.roles import UserRole
62
+ from lino.utils.choosers import discover_choosers
63
63
  from lino.core.store import Store
64
64
  from lino.core.renderer import HtmlRenderer, TextRenderer
65
65
  from lino.core.gfks import ContentType, GenericForeignKey
66
66
  from lino.core.signals import (
67
67
  pre_ui_build,
68
- post_ui_build,
68
+ # post_ui_build,
69
69
  pre_startup,
70
70
  post_startup,
71
71
  pre_analyze,
@@ -83,9 +83,9 @@ from .utils import get_models
83
83
  from .utils import resolve_fields_list
84
84
 
85
85
  # from .utils import djangoname
86
- from .utils import class_dict_items
86
+ # from .utils import class_dict_items
87
87
 
88
- from .fields import set_default_verbose_name
88
+ from lino.core.fields import set_default_verbose_name
89
89
  # from lino.core.requests import ActorRequest
90
90
 
91
91
  startup_rlock = threading.RLock() # Lock() or RLock()?
@@ -155,6 +155,8 @@ class Kernel(object):
155
155
  # # self._code_mtime = codetime(settings.SETTINGS_MODULE)
156
156
  # return self._code_mtime
157
157
 
158
+ editing_front_end = None
159
+
158
160
  def kernel_startup(self, site):
159
161
  """This is a part of a Lino site startup. The Django Model
160
162
  definitions are done, now Lino analyzes them and does certain
@@ -226,22 +228,22 @@ class Kernel(object):
226
228
 
227
229
  if isinstance(model.hidden_columns, str):
228
230
  model.hidden_columns = frozenset(
229
- fields.fields_list(model, model.hidden_columns)
231
+ atomizer.fields_list(model, model.hidden_columns)
230
232
  )
231
233
 
232
234
  if isinstance(model.active_fields, str):
233
235
  model.active_fields = frozenset(
234
- fields.fields_list(model, model.active_fields)
236
+ atomizer.fields_list(model, model.active_fields)
235
237
  )
236
238
 
237
239
  if isinstance(model.allow_cascaded_delete, str):
238
240
  model.allow_cascaded_delete = frozenset(
239
- fields.fields_list(model, model.allow_cascaded_delete)
241
+ atomizer.fields_list(model, model.allow_cascaded_delete)
240
242
  )
241
243
 
242
244
  if isinstance(model.allow_cascaded_copy, str):
243
245
  model.allow_cascaded_copy = frozenset(
244
- fields.fields_list(model, model.allow_cascaded_copy)
246
+ atomizer.fields_list(model, model.allow_cascaded_copy)
245
247
  )
246
248
 
247
249
  # Note how to inherit this from from parent model.
@@ -469,7 +471,7 @@ class Kernel(object):
469
471
  model._lino_default_table = rpt
470
472
 
471
473
  # ~ choosers.discover()
472
- actions.discover_choosers()
474
+ discover_choosers()
473
475
 
474
476
  for a in actors.actors_list:
475
477
  for name, field in a.virtual_fields.items():
@@ -675,13 +677,16 @@ class Kernel(object):
675
677
  # must_remove.add(r)
676
678
  # site.user_roles -= must_remove
677
679
 
678
- post_ui_build.send(self)
680
+ # post_ui_build.send(self)
679
681
 
680
- # trigger creation of params_layout.params_store
682
+ # trigger creation of params_layout.params_store and
683
+ # virtual fields in LightWeightContainer
681
684
  for res in actors.actors_list:
682
685
  for ba in res.get_actions():
683
686
  if ba.action.params_layout is not None:
684
687
  ba.action.params_layout.get_layout_handle()
688
+ if ba.action.is_window_action():
689
+ ba.get_layout_handel()
685
690
 
686
691
  # logger.info("20161219 kernel_startup done")
687
692