lino 24.10.3__py3-none-any.whl → 24.11.0__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 (48) hide show
  1. lino/__init__.py +1 -1
  2. lino/api/doctest.py +11 -10
  3. lino/api/rt.py +2 -3
  4. lino/config/admin_main_base.html +2 -2
  5. lino/core/actors.py +68 -33
  6. lino/core/choicelists.py +2 -2
  7. lino/core/dashboard.py +2 -1
  8. lino/core/dbtables.py +3 -3
  9. lino/core/elems.py +8 -4
  10. lino/core/fields.py +11 -3
  11. lino/core/kernel.py +4 -5
  12. lino/core/layouts.py +1 -1
  13. lino/core/model.py +1 -9
  14. lino/core/plugin.py +1 -0
  15. lino/core/renderer.py +19 -19
  16. lino/core/requests.py +73 -38
  17. lino/core/site.py +5 -45
  18. lino/core/store.py +12 -15
  19. lino/core/tables.py +0 -17
  20. lino/core/utils.py +28 -1
  21. lino/core/views.py +2 -1
  22. lino/help_texts.py +6 -2
  23. lino/management/commands/show.py +2 -4
  24. lino/mixins/periods.py +9 -3
  25. lino/mixins/polymorphic.py +3 -3
  26. lino/mixins/ref.py +6 -3
  27. lino/modlib/checkdata/__init__.py +3 -3
  28. lino/modlib/extjs/ext_renderer.py +1 -1
  29. lino/modlib/linod/consumers.py +2 -3
  30. lino/modlib/memo/mixins.py +1 -1
  31. lino/modlib/periods/__init__.py +12 -1
  32. lino/modlib/periods/fixtures/std.py +2 -1
  33. lino/modlib/periods/models.py +79 -75
  34. lino/modlib/printing/actions.py +2 -0
  35. lino/modlib/publisher/ui.py +2 -2
  36. lino/modlib/system/__init__.py +0 -2
  37. lino/modlib/system/choicelists.py +55 -1
  38. lino/modlib/system/models.py +1 -0
  39. lino/modlib/users/models.py +2 -2
  40. lino/modlib/weasyprint/__init__.py +2 -0
  41. lino/utils/__init__.py +8 -9
  42. lino/utils/djangotest.py +2 -1
  43. lino/utils/html.py +31 -0
  44. {lino-24.10.3.dist-info → lino-24.11.0.dist-info}/METADATA +1 -1
  45. {lino-24.10.3.dist-info → lino-24.11.0.dist-info}/RECORD +48 -48
  46. {lino-24.10.3.dist-info → lino-24.11.0.dist-info}/WHEEL +0 -0
  47. {lino-24.10.3.dist-info → lino-24.11.0.dist-info}/licenses/AUTHORS.rst +0 -0
  48. {lino-24.10.3.dist-info → lino-24.11.0.dist-info}/licenses/COPYING +0 -0
lino/__init__.py CHANGED
@@ -26,7 +26,7 @@ defines no models, some template files, a series of :term:`django-admin commands
26
26
 
27
27
  """
28
28
 
29
- __version__ = '24.10.3'
29
+ __version__ = '24.11.0'
30
30
 
31
31
  # import setuptools # avoid UserWarning "Distutils was imported before Setuptools"?
32
32
 
lino/api/doctest.py CHANGED
@@ -478,7 +478,7 @@ def walk_menu_items(username=None, severe=True):
478
478
  print(s)
479
479
 
480
480
  if settings.SITE.user_types_module:
481
- ar = settings.SITE.login(username)
481
+ ar = rt.login(username)
482
482
  with translation.override(ar.user.language):
483
483
  doit(ar)
484
484
  else:
@@ -642,27 +642,28 @@ def pprint_json_string(s):
642
642
  print(json.dumps(json.loads(s), indent=2, sort_keys=True, separators=(",", ": ")))
643
643
 
644
644
 
645
- def show_dashboard(username, **options):
645
+ def show_dashboard(username, show_urls=False, **options):
646
646
  """Show the dashboard of the given user.
647
647
 
648
648
  Useful options:
649
649
 
650
+ - show_urls=False
650
651
  - ignore_links=True
651
652
 
652
653
  For more options, see
653
654
  https://pypi.org/project/html2text/ and
654
655
  https://github.com/Alir3z4/html2text/blob/master/docs/usage.md
655
656
 
656
- Note that this is currently not much used because the result is difficult to
657
- maintain. One reason for this is that :func:`naturaltime` (from
658
- :mod:`django.contrib.humanize.templatetags.humanize`) ignores demo_date and
659
- therefore produces results that depend on the current date/time.
657
+ This is currently not much used because the result is difficult to maintain.
658
+ One reason for this is that :func:`naturaltime` (from
659
+ :mod:`django.contrib.humanize.templatetags.humanize`) ignores
660
+ :attr:`lino.core.site.Site.the_demo_date` and therefore produces results that
661
+ depend on the current date/time.
660
662
 
661
663
  """
662
- # request = PseudoRequest(username)
663
- rnd = settings.SITE.kernel.text_renderer
664
- ar = rt.login(username, renderer=rnd)
665
- html = settings.SITE.get_main_html(ar) # , front_end=rnd.front_end)
664
+ renderer = settings.SITE.kernel.text_renderer
665
+ ar = rt.login(username, renderer=renderer, show_urls=show_urls)
666
+ html = settings.SITE.get_main_html(ar)
666
667
  print(html2text(html, **options).strip())
667
668
 
668
669
 
lino/api/rt.py CHANGED
@@ -15,7 +15,7 @@ from lino.core.exceptions import ChangedAPI
15
15
 
16
16
  # actors = settings.SITE.models
17
17
 
18
- login = settings.SITE.login
18
+ # login = rt.login
19
19
  startup = settings.SITE.startup
20
20
  # get_printable_context = settings.SITE.get_printable_context
21
21
  lookup_filter = settings.SITE.lookup_filter
@@ -32,8 +32,7 @@ def get_template(*args, **kw):
32
32
  return settings.SITE.plugins.jinja.renderer.jinja_env.get_template(*args, **kw)
33
33
 
34
34
 
35
- def show(*args, **kw):
36
- return login().show(*args, **kw)
35
+ from lino.core.utils import login, show, shows
37
36
 
38
37
 
39
38
  # def send_email(*args, **kw):
@@ -100,8 +100,8 @@
100
100
 
101
101
  {% block admin_main_items %}
102
102
  {% if not ar.renderer.support_dashboard_layout %}
103
- {% for i in user.get_preferences().dashboard_items %}
104
- {{''.join(i.render(ar))}}
103
+ {% for di in user.get_preferences().dashboard_items %}
104
+ {{''.join(di.render(ar))}}
105
105
  {% endfor %}
106
106
  {% endif %}
107
107
  {% endblock %}
lino/core/actors.py CHANGED
@@ -39,7 +39,8 @@ from lino.core.utils import ParameterPanel
39
39
  from lino.core.utils import navinfo, dbfield2params_field
40
40
  from lino.utils import curry, AttrDict, is_string
41
41
 
42
- from lino.utils.html import E, forcetext, tostring, assert_safe
42
+ from lino.utils.html import E, forcetext, tostring, Grouper, SAFE_EMPTY
43
+ # from lino.utils.html import assert_safe
43
44
 
44
45
  from .roles import SiteUser
45
46
 
@@ -283,6 +284,12 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
283
284
  only_fields = None
284
285
 
285
286
  default_display_modes = None
287
+ """
288
+ Which :term:`display mode` to use in a :term:`slave panel`,
289
+ depending on available width.
290
+
291
+ See :ref:`dg.table.default_display_modes`.
292
+ """
286
293
 
287
294
  # extra_display_modes = set()
288
295
  # extra_display_modes = {constants.DISPLAY_MODE_SUMMARY}
@@ -437,6 +444,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
437
444
  detail_template = None # deprecated: use insert_layout instead
438
445
  insert_template = None # deprecated: use detail_layout instead
439
446
 
447
+ row_template = "{row}"
448
+
440
449
  help_text = None
441
450
  detail_action = None
442
451
  update_action = None
@@ -502,6 +511,14 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
502
511
  def is_installed(self):
503
512
  return settings.SITE.is_installed(self.app_label)
504
513
 
514
+ @classmethod
515
+ def before_group_change(cls, gh, row):
516
+ return SAFE_EMPTY
517
+
518
+ @classmethod
519
+ def after_group_change(cls, gh, row):
520
+ return SAFE_EMPTY
521
+
505
522
  @classmethod
506
523
  def is_hidden(self):
507
524
  return settings.SITE.is_hidden_plugin(self.app_label)
@@ -706,8 +723,10 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
706
723
  pass
707
724
 
708
725
  @classmethod
709
- def row_as_summary(cls, ar, obj, *args, **kwargs):
710
- return obj.as_summary_item(ar, *args, **kwargs)
726
+ def row_as_summary(cls, ar, obj, text=None, **kwargs):
727
+ if ar is None:
728
+ return text or str(obj)
729
+ return obj.as_summary_item(ar, text, **kwargs)
711
730
 
712
731
  @classmethod
713
732
  def do_setup(self):
@@ -1775,37 +1794,37 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
1775
1794
  for k, pf in self.parameters.items():
1776
1795
  # if not isinstance(pf, fields.DummyField):
1777
1796
  kw[k] = pf.get_default()
1797
+ if self.model is not None:
1798
+ kw = self.model.param_defaults(ar, **kw)
1778
1799
  return kw
1779
1800
 
1780
1801
  @classmethod
1781
- def request(self, *args, **kw):
1782
- """
1783
- Return an action request on this actor.
1784
- """
1785
- kw.update(actor=self)
1786
- from lino.core.requests import ActionRequest
1787
- return ActionRequest(*args, **kw)
1802
+ def request(cls, master_instance=None, **kwargs):
1803
+ """Return a new :class:`ActionRequest
1804
+ <lino.core.requests.ActionRequest>` on this actor.
1788
1805
 
1789
- @classmethod
1790
- def request_from(cls, ar, *args, **kwargs):
1791
- """
1792
- Return an action request on this actor which inherits from the
1793
- given parent request.
1806
+ The :attr:`master_instance
1807
+ <lino.core.requests.ActionRequest.master_instance>` can be
1808
+ specified as optional first positional argument.
1794
1809
 
1795
- Deprecated. Rather call cls.request(parent=ar)
1796
1810
  """
1797
- raise Exception(
1798
- "Deprecated (Actor.request_from). Rather call cls.request(parent=ar)"
1799
- )
1800
- # logger.warning("Deprecated (Actor.request_from). Rather call cls.request(parent=ar)")
1801
- sar = cls.request(*args, **kwargs)
1802
- sar.setup_from(ar)
1803
- return sar
1811
+ from lino.core.requests import ActionRequest
1812
+ kwargs.update(actor=cls)
1813
+ kwargs.setdefault("action", cls.default_action)
1814
+ if master_instance is not None:
1815
+ kwargs.update(master_instance=master_instance)
1816
+ # kw.setdefault("renderer", settings.SITE.kernel.text_renderer)
1817
+ return ActionRequest(**kwargs)
1818
+
1819
+ # @classmethod
1820
+ # def show(cls, master_instance=None, renderer=None, **kwargs):
1821
+ # if renderer is None:
1822
+ # renderer = settings.SITE.kernel.text_renderer
1823
+ # ar = cls.request(master_instance, renderer=renderer)
1824
+ # ar.show(**kwargs)
1804
1825
 
1805
1826
  @classmethod
1806
1827
  def to_html(self, **kw):
1807
- """ """
1808
- # ~ settings.SITE.startup()
1809
1828
  return tostring(self.request(**kw).table2xhtml())
1810
1829
 
1811
1830
  @classmethod
@@ -1828,7 +1847,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
1828
1847
  # print(f"20240914 slave_as_html() {ar.request}")
1829
1848
 
1830
1849
  # 20240911 We don't want to re-parse the original request, especially
1831
- # because it might contain disturbing things like selected_pks. But he
1850
+ # because it might contain disturbing things like selected_pks. But the
1832
1851
  # slave must at least inherit the user, as shown in
1833
1852
  # welfare/docs/specs/weleup/weleup1r.rst
1834
1853
  # kwargs.update(request=ar.request)
@@ -1836,15 +1855,12 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
1836
1855
  kwargs.update(renderer=settings.SITE.kernel.default_renderer)
1837
1856
  try:
1838
1857
  ar = cls.request(master_instance=master, **kwargs)
1839
- el = ar.table2xhtml()
1840
- toolbar = ar.plain_toolbar_buttons()
1858
+ el = cls.table_as_html(ar)
1841
1859
  except Exception as e:
1842
1860
  msg = f"20241004 Error in {repr(ar)}: {e}"
1843
1861
  raise Exception(msg) from e
1844
1862
  logger.warning(msg)
1845
1863
  return msg
1846
- if len(toolbar):
1847
- el = E.div(el, E.p(*toolbar))
1848
1864
  return el
1849
1865
 
1850
1866
  # summary_sep = "<br/>"
@@ -1854,7 +1870,8 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
1854
1870
  def get_table_as_list(cls, obj, ar):
1855
1871
  # raise Exception("20240316")
1856
1872
  sar = cls.request(parent=ar, master_instance=obj, is_on_main_actor=False)
1857
- html_text = mark_safe("")
1873
+ grp = Grouper(sar)
1874
+ html_text = grp.begin()
1858
1875
  for i, obj in enumerate(sar.data_iterator):
1859
1876
  if i == cls.preview_limit:
1860
1877
  break
@@ -1870,7 +1887,10 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
1870
1887
  # else: # a funny way to debug:
1871
1888
  # par = '<a href="{}">{}</a>'.format(str(sar.renderer), par)
1872
1889
 
1890
+ html_text += grp.before_row(obj)
1873
1891
  html_text += par
1892
+ html_text += grp.after_row(obj)
1893
+ html_text += grp.stop()
1874
1894
 
1875
1895
  if cls.editable and cls.insert_action is not None:
1876
1896
  ir = cls.insert_action.request_from(sar)
@@ -1884,7 +1904,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
1884
1904
  @classmethod
1885
1905
  def get_table_story(cls, obj, ar):
1886
1906
  sar = cls.request(parent=ar, master_instance=obj, is_on_main_actor=False)
1887
- html = mark_safe("")
1907
+ html = SAFE_EMPTY
1888
1908
  for i, obj in enumerate(sar.data_iterator):
1889
1909
  if i == cls.preview_limit:
1890
1910
  break
@@ -1901,7 +1921,7 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
1901
1921
  return html
1902
1922
 
1903
1923
  @classmethod
1904
- def get_table_summary(cls, obj, ar):
1924
+ def get_table_summary(cls, obj, ar=None):
1905
1925
  """
1906
1926
  Return the HTML `<div>` to be displayed by
1907
1927
  :class:`lino.core.elems.TableSummaryPanel`.
@@ -1952,6 +1972,21 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
1952
1972
  p += tostring(b) + btn_sep
1953
1973
  return p
1954
1974
 
1975
+ @classmethod
1976
+ def table_as_html(cls, ar):
1977
+ """
1978
+ Return an ElementTree element that represents the given action
1979
+ request `ar` on this actor in :term:`display mode` "HTML".
1980
+
1981
+ An :term:`application developer` may override this method. Usage example
1982
+ is :class:`lino_prima.lib.prima.PupilsAndProjects`.
1983
+
1984
+ """
1985
+ el = ar.table2xhtml()
1986
+ if len(toolbar := ar.plain_toolbar_buttons()):
1987
+ el = E.div(el, E.p(*toolbar))
1988
+ return el
1989
+
1955
1990
  @classmethod
1956
1991
  def columns_to_paragraph(cls, self, ar=None, fmt=None):
1957
1992
  """
lino/core/choicelists.py CHANGED
@@ -246,9 +246,9 @@ Django creates copies of them when inheriting models.
246
246
  def get_chooser_for_field(cls, fieldname):
247
247
  return None
248
248
 
249
- def as_summary_item(self, ar, *args, **kwargs):
249
+ def as_summary_item(self, ar, text=None, **kwargs):
250
250
  # needed by `detail_pointer`
251
- return str(self)
251
+ return text or str(self)
252
252
 
253
253
 
254
254
  class UnresolvedValue(Choice):
lino/core/dashboard.py CHANGED
@@ -5,6 +5,7 @@
5
5
 
6
6
  """
7
7
 
8
+ from django.conf import settings
8
9
  from lino.api import _
9
10
  from lino.core.permissions import Permittable
10
11
  from lino.core.requests import ActionRequest
@@ -148,7 +149,7 @@ class ActorItem(DashboardItem):
148
149
  # from lino.core.tables import AbstractTable
149
150
  T = self.actor
150
151
  # if isinstance(T, AbstractTable):
151
- sar = T.request(limit=T.preview_limit, parent=ar)
152
+ sar = T.request(limit=T.preview_limit, parent=ar) #, renderer=settings.SITE.kernel.default_renderer)
152
153
  # sar = ar.spawn(T, limit=T.preview_limit)
153
154
  # sar = ar.spawn_request(actor=T, limit=T.preview_limit)
154
155
  # raise Exception("20230331 {}".format(ar.subst_user))
lino/core/dbtables.py CHANGED
@@ -201,9 +201,9 @@ class Table(AbstractTable):
201
201
  """If when in a detail view will override default param values with the detail's pv values.
202
202
  """
203
203
 
204
- react_responsive = True
205
- """If viewing the grid view on a mobile, should the grid use responsive mode
206
- Default: True"""
204
+ # react_responsive = True
205
+ # """If viewing the grid view on a mobile, should the grid use responsive mode
206
+ # Default: True"""
207
207
 
208
208
  # react_big_search = False
209
209
  """If True will position the quick search input to the bottom of the header and have it full width.
lino/core/elems.py CHANGED
@@ -671,7 +671,7 @@ class FieldElement(LayoutElement):
671
671
  return kw
672
672
 
673
673
  def ext_options(self, **kw):
674
- kw = LayoutElement.ext_options(self, **kw)
674
+ kw = super().ext_options(**kw)
675
675
  kw.update(self.get_field_options())
676
676
  return kw
677
677
 
@@ -1565,6 +1565,10 @@ class BooleanDisplayElement(DisplayElement):
1565
1565
  # kw.update(always_enabled=True)
1566
1566
  FieldElement.__init__(self, *args, **kw)
1567
1567
 
1568
+ def value2html(self, ar, v, **cellattrs):
1569
+ txt = self.format_value(ar, v)
1570
+ return E.td(txt, **cellattrs)
1571
+
1568
1572
 
1569
1573
  class BooleanFieldElement(FieldElement):
1570
1574
  value_template = "new Ext.form.Checkbox(%s)"
@@ -2534,7 +2538,7 @@ class TabPanel(Panel):
2534
2538
  # self.reactive_elem_name = actor.reactive_elem_name
2535
2539
  # super().__init__(lh, actor, **kw)
2536
2540
 
2537
- _FIELD2ELEM = (
2541
+ _FIELD2ELEM = [
2538
2542
  # (dd.Constant, ConstantElement),
2539
2543
  (fields.RecurrenceField, RecurrenceElement),
2540
2544
  (fields.DelayedHtmlBox, DisplayElement),
@@ -2555,7 +2559,7 @@ _FIELD2ELEM = (
2555
2559
  (models.JSONField, CharFieldElement), # workaround
2556
2560
  (fields.PasswordField, PasswordFieldElement),
2557
2561
  (models.CharField, CharFieldElement),
2558
- (fields.MeasurementField, CharFieldElement),
2562
+ # (fields.MeasurementField, CharFieldElement),
2559
2563
  (fields.MonthField, MonthFieldElement),
2560
2564
  (models.DateTimeField, DateTimeFieldElement),
2561
2565
  (fields.DatePickerField, DatePickerFieldElement),
@@ -2569,7 +2573,7 @@ _FIELD2ELEM = (
2569
2573
  (models.NullBooleanField, BooleanFieldElement),
2570
2574
  # (models.ManyToManyField, M2mGridElement),
2571
2575
  (models.ForeignKey, ForeignKeyElement),
2572
- )
2576
+ ]
2573
2577
 
2574
2578
  TRIGGER_BUTTON_WIDTH = 3
2575
2579
 
lino/core/fields.py CHANGED
@@ -1264,6 +1264,10 @@ class TableRow(object):
1264
1264
  """
1265
1265
  return []
1266
1266
 
1267
+ @classmethod
1268
+ def param_defaults(self, ar, **kw):
1269
+ return kw
1270
+
1267
1271
  @classmethod
1268
1272
  def get_title_tags(self, ar):
1269
1273
  return []
@@ -1353,6 +1357,8 @@ class TableRow(object):
1353
1357
 
1354
1358
  @htmlbox()
1355
1359
  def list_item(self, ar):
1360
+ if ar is None:
1361
+ return escape(str(self))
1356
1362
  return self.as_paragraph(ar)
1357
1363
 
1358
1364
  def get_overview_elems(self, ar):
@@ -1363,9 +1369,14 @@ class TableRow(object):
1363
1369
  # must return an ET element
1364
1370
  if ar is None:
1365
1371
  return text or str(self)
1372
+ if text is None and ar.actor is not None:
1373
+ text = ar.actor.row_template.format(row=self)
1374
+ # raise Exception("20241029")
1366
1375
  return ar.obj2html(self, text, **kwargs)
1367
1376
 
1368
1377
  def as_paragraph(self, ar, **kwargs):
1378
+ if ar is None:
1379
+ return escape(str(self))
1369
1380
  return tostring(self.as_summary_item(ar, **kwargs))
1370
1381
 
1371
1382
  def as_story_item(self, ar, **kwargs):
@@ -1752,6 +1763,3 @@ def choices_for_field(ar, holder, field):
1752
1763
  else:
1753
1764
  raise http.Http404("No choices for %s" % field)
1754
1765
  return (qs, row2dict)
1755
-
1756
-
1757
- from lino_xl.lib.measurements.fields import MeasurementField
lino/core/kernel.py CHANGED
@@ -867,7 +867,7 @@ class Kernel(object):
867
867
  every actor handle because it potentially requires other actor
868
868
  handles to be instantiated.
869
869
 
870
- ar is usually None, except for actors with dynamic handle
870
+ `ar` is usually None, except for actors with dynamic handle
871
871
  """
872
872
  # logger.info('20121010 Kernel.setup_handle() %s', h.actor)
873
873
 
@@ -877,10 +877,9 @@ class Kernel(object):
877
877
 
878
878
  if isinstance(h, tables.TableHandle):
879
879
  he = set(h.actor.hidden_columns | h.actor.hidden_elements)
880
- gl = layouts.ColumnsLayout(
881
- h.actor.get_column_names(ar), h.actor, hidden_elements=he
882
- )
883
- h.grid_layout = gl.get_layout_handle()
880
+ cl = layouts.ColumnsLayout(
881
+ h.actor.get_column_names(ar), h.actor, hidden_elements=he)
882
+ h.grid_layout = cl.get_layout_handle()
884
883
  else:
885
884
  h.grid_layout = None
886
885
 
lino/core/layouts.py CHANGED
@@ -785,7 +785,7 @@ class ColumnsLayout(FieldLayout):
785
785
  def set_datasource(self, ds):
786
786
  if ds is None:
787
787
  raise Exception("20130327 No datasource for %r" % self)
788
- super(ColumnsLayout, self).set_datasource(ds)
788
+ super().set_datasource(ds)
789
789
 
790
790
 
791
791
  class ParamsLayout(BaseLayout):
lino/core/model.py CHANGED
@@ -623,15 +623,6 @@ class Model(models.Model, fields.TableRow):
623
623
  def name_column(self, ar):
624
624
  return str(self)
625
625
 
626
- # @fields.displayfield(_("Description"))
627
- # def mobile_item(self, ar):
628
- # if ar is None:
629
- # return ''
630
- # return E.div(*forcetext(self.get_mobile_list_item_elems(ar)))
631
- #
632
- # def get_mobile_list_item_elems(self, ar):
633
- # return [self.as_summary_item(ar)]
634
-
635
626
  @fields.htmlbox()
636
627
  def navigation_panel(self, ar):
637
628
  # if not isinstance(ar, ActionRequest):
@@ -934,6 +925,7 @@ LINO_MODEL_ATTRIBS = (
934
925
  "workflow_buttons",
935
926
  "delete_instance",
936
927
  "setup_parameters",
928
+ "param_defaults",
937
929
  "add_param_filter",
938
930
  "save_new_instance",
939
931
  "save_watched_instance",
lino/core/plugin.py CHANGED
@@ -7,6 +7,7 @@ import inspect
7
7
  from os.path import exists, join, dirname, isdir, abspath
8
8
  from collections.abc import Iterable
9
9
  from urllib.parse import urlencode
10
+ from lino.core.exceptions import ChangedAPI
10
11
 
11
12
 
12
13
  class Plugin:
lino/core/renderer.py CHANGED
@@ -262,7 +262,6 @@ class HtmlRenderer(Renderer):
262
262
  ar,
263
263
  nosummary=False,
264
264
  stripped=True,
265
- show_urls=False,
266
265
  header_level=None,
267
266
  display_mode=None,
268
267
  **kwargs
@@ -766,28 +765,27 @@ class TextRenderer(HtmlRenderer):
766
765
  """
767
766
 
768
767
  user = None
769
- show_urls = False
770
768
  link_url = mark_safe("…") # U+2026 Horizontal Ellipsis
771
769
 
772
770
  def __init__(self, *args, **kw):
773
- HtmlRenderer.__init__(self, *args, **kw)
771
+ super().__init__(*args, **kw)
774
772
  self.user = None
775
773
 
776
774
  def get_request_url(self, ar, *args, **kw):
777
- if self.show_urls:
775
+ if ar.show_urls:
778
776
  return super().get_request_url(ar, *args, **kw)
779
777
  return self.link_url
780
778
  # return None
781
779
 
782
780
  def obj2url(self, ar, obj):
783
- if self.show_urls:
781
+ if ar.show_urls:
784
782
  return super().obj2url(ar, obj)
785
783
  return self.link_url
786
784
  # return None
787
785
 
788
- def get_detail_url(self, *args, **kwargs):
789
- if self.show_urls:
790
- return super().get_detail_url(*args, **kwargs)
786
+ def get_detail_url(self, ar, *args, **kwargs):
787
+ if ar.show_urls:
788
+ return super().get_detail_url(ar, *args, **kwargs)
791
789
  return self.link_url
792
790
 
793
791
  # # return str(actor)+"/"+str(pk)
@@ -815,7 +813,7 @@ class TextRenderer(HtmlRenderer):
815
813
  header_links=None,
816
814
  nosummary=False,
817
815
  stripped=True,
818
- show_urls=False,
816
+ show_links=False, # added 20241031
819
817
  display_mode=None,
820
818
  **kwargs
821
819
  ):
@@ -823,9 +821,9 @@ class TextRenderer(HtmlRenderer):
823
821
  Render the given table request as reStructuredText to stdout. See
824
822
  :meth:`ar.show <lino.core.request.BaseRequest.show>`.
825
823
  """
826
- self.show_urls = show_urls
827
824
  if display_mode is None:
828
825
  display_mode = ar.actor.get_display_mode()
826
+ # display_mode = constants.DISPLAY_MODE_GRID
829
827
  if nosummary and display_mode == constants.DISPLAY_MODE_SUMMARY:
830
828
  display_mode = constants.DISPLAY_MODE_GRID
831
829
  else:
@@ -874,6 +872,16 @@ class TextRenderer(HtmlRenderer):
874
872
  yield rstgen.ul(items).strip()
875
873
  return
876
874
 
875
+ # At this point, display_mode is one of story, grid or html.
876
+
877
+ if header_level is not None:
878
+ h = rstgen.header(header_level, ar.get_title())
879
+ if stripped:
880
+ h = h.strip()
881
+ yield h
882
+ # s = h + "\n" + s
883
+ # s = tostring(E.h2(ar.get_title())) + s
884
+
877
885
  fields, headers, widths = ar.get_field_info(column_names)
878
886
 
879
887
  # if str(ar.actor) == "working.WorkedHours":
@@ -884,7 +892,7 @@ class TextRenderer(HtmlRenderer):
884
892
  recno = 0
885
893
  for row in ar.sliced_data_iterator:
886
894
  recno += 1
887
- if show_urls:
895
+ if ar.show_urls or show_links:
888
896
  rows.append([to_rst(x) for x in ar.row2html(recno, fields, row, sums)])
889
897
  else:
890
898
  # only for debugging:
@@ -898,14 +906,6 @@ class TextRenderer(HtmlRenderer):
898
906
  # return a SafeString
899
907
  rows.append([text2rst(x) for x in ar.row2text(fields, row, sums)])
900
908
 
901
- if header_level is not None:
902
- h = rstgen.header(header_level, ar.get_title())
903
- if stripped:
904
- h = h.strip()
905
- yield h
906
- # s = h + "\n" + s
907
- # s = tostring(E.h2(ar.get_title())) + s
908
-
909
909
  # if str(ar.actor) == "working.WorkedHours":
910
910
  # yield "20200306 rows {}".format(rows)
911
911
  if len(rows) == 0: