lino 25.3.0__py3-none-any.whl → 25.3.2__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 +6 -7
- lino/api/dd.py +1 -0
- lino/api/doctest.py +35 -102
- lino/api/rt.py +2 -4
- lino/core/actors.py +22 -16
- lino/core/boundaction.py +17 -7
- lino/core/dashboard.py +5 -4
- lino/core/dbtables.py +15 -16
- lino/core/fields.py +3 -3
- lino/core/inject.py +7 -6
- lino/core/kernel.py +0 -46
- lino/core/menus.py +1 -1
- lino/core/model.py +18 -16
- lino/core/plugin.py +4 -4
- lino/core/renderer.py +10 -11
- lino/core/requests.py +11 -7
- lino/core/site.py +84 -30
- lino/core/tables.py +2 -2
- lino/core/utils.py +3 -3
- lino/core/views.py +3 -3
- lino/help_texts.py +1 -0
- lino/management/commands/buildsite.py +57 -0
- lino/management/commands/initdb.py +12 -14
- lino/management/commands/prep.py +1 -1
- lino/mixins/sequenced.py +1 -1
- lino/modlib/comments/models.py +1 -1
- lino/modlib/comments/ui.py +2 -2
- lino/modlib/extjs/ext_renderer.py +2 -2
- lino/modlib/extjs/views.py +50 -48
- lino/modlib/help/config/makehelp/model.tpl.rst +1 -1
- lino/modlib/help/management/commands/makehelp.py +11 -7
- lino/modlib/jinja/mixins.py +2 -2
- lino/modlib/jinja/renderer.py +2 -2
- lino/modlib/linod/management/commands/linod.py +5 -2
- lino/modlib/linod/mixins.py +3 -0
- lino/modlib/memo/__init__.py +1 -1
- lino/modlib/printing/mixins.py +3 -0
- lino/modlib/publisher/choicelists.py +3 -3
- lino/modlib/publisher/views.py +2 -2
- lino/modlib/search/models.py +5 -5
- lino/modlib/system/choicelists.py +6 -3
- lino/modlib/tinymce/views.py +1 -1
- lino/modlib/uploads/models.py +7 -6
- lino/modlib/users/ui.py +2 -3
- lino/utils/__init__.py +4 -1
- lino/utils/diag.py +1 -1
- lino/utils/fieldutils.py +79 -0
- {lino-25.3.0.dist-info → lino-25.3.2.dist-info}/METADATA +1 -1
- {lino-25.3.0.dist-info → lino-25.3.2.dist-info}/RECORD +52 -71
- 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.3.0.dist-info → lino-25.3.2.dist-info}/WHEEL +0 -0
- {lino-25.3.0.dist-info → lino-25.3.2.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.3.0.dist-info → lino-25.3.2.dist-info}/licenses/COPYING +0 -0
lino/core/model.py
CHANGED
@@ -534,6 +534,7 @@ class Model(models.Model, fields.TableRow):
|
|
534
534
|
"""
|
535
535
|
watcher = ChangeWatcher(row)
|
536
536
|
# assert hasattr(row, state_field.attname)
|
537
|
+
row.before_ui_save(ar, watcher) # added 20250312 for #5976
|
537
538
|
old = getattr(row, state_field.attname)
|
538
539
|
target_state.choicelist.before_state_change(row, ar, old, target_state)
|
539
540
|
row.before_state_change(ar, old, target_state)
|
@@ -603,7 +604,7 @@ class Model(models.Model, fields.TableRow):
|
|
603
604
|
database query and show this value as the search result.
|
604
605
|
|
605
606
|
"""
|
606
|
-
ar = self.__class__.get_default_table().
|
607
|
+
ar = self.__class__.get_default_table().create_request()
|
607
608
|
return self.as_search_item(ar)
|
608
609
|
|
609
610
|
# def summary_row(self, ar, **kw):
|
@@ -680,21 +681,22 @@ class Model(models.Model, fields.TableRow):
|
|
680
681
|
|
681
682
|
df = actor.get_disabled_fields(obj, ar)
|
682
683
|
# print(20170909, df)
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
if
|
691
|
-
if
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
684
|
+
if 'workflow_buttons' not in df:
|
685
|
+
for ba in actor.get_actions():
|
686
|
+
assert ba.actor == actor # 20170102
|
687
|
+
if ba.action.show_in_workflow:
|
688
|
+
# if actor.model.__name__ == 'Vote':
|
689
|
+
# if ba.action.__class__.__name__ == 'MarkVoteAssigned':
|
690
|
+
# print(20170115, actor, ar.get_user())
|
691
|
+
if ba.action.action_name not in df:
|
692
|
+
if actor.get_row_permission(obj, ar, state, ba):
|
693
|
+
if show and isinstance(ba.action, ChangeStateAction):
|
694
|
+
show_state()
|
695
|
+
sep = " \u2192 " # "→"
|
696
|
+
show = False
|
697
|
+
l.append(sep)
|
698
|
+
l.append(ar.action_button(ba, obj))
|
699
|
+
sep = " "
|
698
700
|
if state and show:
|
699
701
|
show_state()
|
700
702
|
return E.span(*l)
|
lino/core/plugin.py
CHANGED
@@ -1,10 +1,9 @@
|
|
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
|
-
import os
|
6
5
|
import inspect
|
7
|
-
from os.path import
|
6
|
+
from os.path import join, dirname, isdir, abspath
|
8
7
|
from collections.abc import Iterable
|
9
8
|
from urllib.parse import urlencode
|
10
9
|
from lino.core.exceptions import ChangedAPI
|
@@ -56,7 +55,8 @@ class Plugin:
|
|
56
55
|
|
57
56
|
def hide(self):
|
58
57
|
if self.site._startup_done:
|
59
|
-
raise Exception(
|
58
|
+
raise Exception(
|
59
|
+
"Tried to deactivate plugin {} after startup".format(self))
|
60
60
|
self.hidden = True
|
61
61
|
|
62
62
|
def configure(self, **kw):
|
lino/core/renderer.py
CHANGED
@@ -197,7 +197,7 @@ class HtmlRenderer(Renderer):
|
|
197
197
|
import rstgen
|
198
198
|
|
199
199
|
if display_mode == constants.DISPLAY_MODE_CARDS:
|
200
|
-
layout = ar.actor.card_layout
|
200
|
+
layout = ar.actor.card_layout # or ar.actor.list_layout
|
201
201
|
lh = layout.get_layout_handle()
|
202
202
|
else:
|
203
203
|
lh = ar.bound_action.get_layout_handel()
|
@@ -320,13 +320,12 @@ class HtmlRenderer(Renderer):
|
|
320
320
|
Return a string of Javascript code that would open a detail window
|
321
321
|
on the given database object.
|
322
322
|
"""
|
323
|
-
status.update(record_id=obj.pk)
|
324
|
-
|
325
323
|
if ba is None:
|
326
324
|
ba = obj.get_detail_action(ar)
|
327
325
|
# ba = obj.__class__.get_default_table().detail_action
|
328
|
-
# print(20180831, ba.get_view_permission(ar.get_user().user_type))
|
329
326
|
if ba is not None:
|
327
|
+
# print(f"20250319 instance_handler {ba} {status} {self.action_call}")
|
328
|
+
status.update(record_id=obj.pk)
|
330
329
|
return self.action_call(ar, ba, status)
|
331
330
|
|
332
331
|
def href_to(self, ar, obj, text=None):
|
@@ -641,7 +640,7 @@ class HtmlRenderer(Renderer):
|
|
641
640
|
# 20200501 elems.append(item)
|
642
641
|
elems.append(tostring(item))
|
643
642
|
elif isinstance(item, type) and issubclass(item, Actor):
|
644
|
-
ar = item.default_action.
|
643
|
+
ar = item.default_action.create_request(parent=ar)
|
645
644
|
# 20200501 elems.extend(self.table2story(ar, **kwargs))
|
646
645
|
elems += [tostring(e) for e in self.table2story(ar, **kwargs)]
|
647
646
|
elif isinstance(item, ActionRequest):
|
@@ -649,12 +648,12 @@ class HtmlRenderer(Renderer):
|
|
649
648
|
if issubclass(item.actor, AbstractTable):
|
650
649
|
# 20200501 elems.extend(self.table2story(item, **kwargs))
|
651
650
|
elems += [tostring(e)
|
652
|
-
|
651
|
+
for e in self.table2story(item, **kwargs)]
|
653
652
|
else:
|
654
653
|
# example : courses.StatusReport in dashboard
|
655
654
|
# 20200501 elems.append(self.show_story(ar, item.actor.get_story(None, ar), **kwargs))
|
656
655
|
elems += [tostring(e)
|
657
|
-
|
656
|
+
for e in self.show_story(
|
658
657
|
ar, item.actor.get_story(None, ar), **kwargs)]
|
659
658
|
elif isinstance(item, DashboardItem):
|
660
659
|
elems.extend(item.render(ar, **kwargs))
|
@@ -707,7 +706,7 @@ class HtmlRenderer(Renderer):
|
|
707
706
|
if not isinstance(mnu, Menu):
|
708
707
|
assert isinstance(mnu, MenuItem)
|
709
708
|
if mnu.bound_action:
|
710
|
-
sar = mnu.bound_action.actor.
|
709
|
+
sar = mnu.bound_action.actor.create_request(
|
711
710
|
action=mnu.bound_action,
|
712
711
|
user=ar.user,
|
713
712
|
subst_user=ar.subst_user,
|
@@ -812,7 +811,7 @@ class TextRenderer(HtmlRenderer):
|
|
812
811
|
header_links=None,
|
813
812
|
nosummary=False,
|
814
813
|
stripped=True,
|
815
|
-
show_links=False,
|
814
|
+
show_links=False, # added 20241031
|
816
815
|
display_mode=None,
|
817
816
|
**kwargs
|
818
817
|
):
|
@@ -938,7 +937,7 @@ class TextRenderer(HtmlRenderer):
|
|
938
937
|
if iselement(item):
|
939
938
|
print(to_rst(item, stripped))
|
940
939
|
elif isinstance(item, type) and issubclass(item, Actor):
|
941
|
-
ar = item.default_action.
|
940
|
+
ar = item.default_action.create_request(parent=ar)
|
942
941
|
self.show_table(ar, stripped=stripped, **kwargs)
|
943
942
|
elif isinstance(item, DashboardItem):
|
944
943
|
self.show_story(ar, item.get_story(ar), stripped, **kwargs)
|
@@ -1029,7 +1028,7 @@ class JsRenderer(HtmlRenderer):
|
|
1029
1028
|
"""Instruct the client to display a detail window on the given
|
1030
1029
|
record.
|
1031
1030
|
"""
|
1032
|
-
# print("
|
1031
|
+
# print("20250319 goto_instance", ar.get_user(), obj, detail_action, js)
|
1033
1032
|
js = self.instance_handler(ar, obj, detail_action)
|
1034
1033
|
kw.update(eval_js=js)
|
1035
1034
|
ar.set_response(**kw)
|
lino/core/requests.py
CHANGED
@@ -783,14 +783,14 @@ class BaseRequest:
|
|
783
783
|
spec.setup_from(self)
|
784
784
|
elif isinstance(spec, BoundAction):
|
785
785
|
kw.update(parent=self)
|
786
|
-
spec = spec.
|
786
|
+
spec = spec.create_request(**kw)
|
787
787
|
else:
|
788
788
|
kw.update(parent=self)
|
789
789
|
ba = resolve_action(spec)
|
790
|
-
spec = ba.
|
790
|
+
spec = ba.create_request(**kw)
|
791
791
|
# from lino.core.menus import create_item
|
792
792
|
# mi = create_item(spec)
|
793
|
-
# spec = mi.bound_action.
|
793
|
+
# spec = mi.bound_action.create_request(**kw)
|
794
794
|
return spec
|
795
795
|
|
796
796
|
def get_printable_context(self, **kw):
|
@@ -1011,10 +1011,14 @@ class BaseRequest:
|
|
1011
1011
|
# # deprecated?
|
1012
1012
|
# self.append_message('warning', msg, *args, **kw)
|
1013
1013
|
|
1014
|
-
debug
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1014
|
+
def debug(self, *args, **kwargs):
|
1015
|
+
return self.logger.debug(*args, **kwargs)
|
1016
|
+
|
1017
|
+
def info(self, *args, **kwargs):
|
1018
|
+
return self.logger.info(*args, **kwargs)
|
1019
|
+
|
1020
|
+
def warning(self, *args, **kwargs):
|
1021
|
+
return self.logger.warning(*args, **kwargs)
|
1018
1022
|
|
1019
1023
|
async def adebug(self, *args, **kwargs):
|
1020
1024
|
return await self.alogger.debug(*args, **kwargs)
|
lino/core/site.py
CHANGED
@@ -3,17 +3,37 @@
|
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
# doctest lino/core/site.py
|
5
5
|
|
6
|
+
import json
|
7
|
+
from lino.core.exceptions import ChangedAPI
|
8
|
+
from lino.core.utils import get_models, is_logserver
|
9
|
+
from lino.utils.html import E, tostring
|
10
|
+
from lino import assert_django_code, DJANGO_DEFAULT_LANGUAGE
|
11
|
+
# from lino.core import constants
|
12
|
+
from lino.core.plugin import Plugin
|
13
|
+
from lino.core.utils import full_model_name as fmn
|
14
|
+
from rstgen.confparser import ConfigParser
|
15
|
+
from django.utils import translation
|
16
|
+
from django.utils.html import mark_safe
|
17
|
+
from django.utils.translation import get_language
|
18
|
+
from django.utils.translation import gettext_lazy as _
|
19
|
+
from django.conf import settings
|
20
|
+
import rstgen
|
21
|
+
from lino.utils import AttrDict, date_offset, i2d, buildurl
|
22
|
+
from lino import logger, __version__
|
23
|
+
from importlib.util import find_spec
|
24
|
+
from importlib import import_module, reload
|
25
|
+
from pathlib import Path
|
6
26
|
import os
|
7
27
|
import re
|
8
28
|
import sys
|
9
|
-
from os.path import
|
29
|
+
from os.path import dirname, join, isdir, relpath, exists
|
10
30
|
import inspect
|
11
31
|
import datetime
|
12
32
|
import warnings
|
13
33
|
import collections
|
14
34
|
import locale
|
15
35
|
import logging
|
16
|
-
from pprint import pprint
|
36
|
+
# from pprint import pprint
|
17
37
|
from logging.handlers import SocketHandler
|
18
38
|
import time
|
19
39
|
|
@@ -30,34 +50,12 @@ ASYNC_LOGGING = False
|
|
30
50
|
# activated, accesses settings.DEFAULT_EXCEPTION_REPORTER, which fails at this
|
31
51
|
# moment because the settings aren't yet loaded.
|
32
52
|
|
33
|
-
from pathlib import Path
|
34
|
-
from importlib import import_module, reload
|
35
|
-
from importlib.util import find_spec
|
36
|
-
|
37
|
-
from lino import logger, __version__
|
38
|
-
from lino.utils import AttrDict, date_offset, i2d, buildurl
|
39
|
-
import rstgen
|
40
|
-
|
41
|
-
from django.conf import settings
|
42
|
-
from django.utils.translation import gettext_lazy as _
|
43
|
-
from django.utils.translation import get_language
|
44
|
-
from django.utils.html import mark_safe
|
45
|
-
from django.db.utils import DatabaseError
|
46
|
-
from django.utils import translation
|
47
53
|
|
48
54
|
has_socialauth = find_spec("social_django") is not None
|
49
55
|
has_elasticsearch = find_spec("elasticsearch_django") is not None
|
50
56
|
has_haystack = find_spec("haystack") is not None
|
51
57
|
|
52
|
-
from rstgen.confparser import ConfigParser
|
53
|
-
from lino.core.plugin import Plugin
|
54
|
-
from lino.core import constants
|
55
|
-
|
56
|
-
from lino import assert_django_code, DJANGO_DEFAULT_LANGUAGE
|
57
|
-
from lino.utils.html import E, join_elems, tostring
|
58
|
-
from lino.core.utils import get_models, is_logserver
|
59
58
|
|
60
|
-
from lino.core.exceptions import ChangedAPI
|
61
59
|
# from .roles import SiteUser
|
62
60
|
|
63
61
|
|
@@ -88,14 +86,14 @@ def to_locale(language):
|
|
88
86
|
p = language.find("-")
|
89
87
|
if p >= 0:
|
90
88
|
# Get correct locale for sr-latn
|
91
|
-
if len(language[p + 1
|
89
|
+
if len(language[p + 1:]) > 2:
|
92
90
|
return (
|
93
91
|
language[:p].lower()
|
94
92
|
+ "_"
|
95
93
|
+ language[p + 1].upper()
|
96
|
-
+ language[p + 2
|
94
|
+
+ language[p + 2:].lower()
|
97
95
|
)
|
98
|
-
return language[:p].lower() + "_" + language[p + 1
|
96
|
+
return language[:p].lower() + "_" + language[p + 1:].upper()
|
99
97
|
return language.lower()
|
100
98
|
|
101
99
|
|
@@ -103,7 +101,8 @@ def class2str(cl):
|
|
103
101
|
return cl.__module__ + "." + cl.__name__
|
104
102
|
|
105
103
|
|
106
|
-
gettext_noop
|
104
|
+
def gettext_noop(s): return s
|
105
|
+
|
107
106
|
|
108
107
|
PLUGIN_CONFIGS = {}
|
109
108
|
|
@@ -718,7 +717,6 @@ class Site(object):
|
|
718
717
|
else:
|
719
718
|
d["logger_ok"] = True
|
720
719
|
# self.update_settings(LOGGING=d)
|
721
|
-
# from pprint import pprint
|
722
720
|
# pprint(d)
|
723
721
|
# print("20161126 Site %s " % d['loggers'].keys())
|
724
722
|
# import yaml
|
@@ -1796,6 +1794,61 @@ class Site(object):
|
|
1796
1794
|
# ~ return v
|
1797
1795
|
# ~ return getattr(obj,attrname,*args)
|
1798
1796
|
|
1797
|
+
def mark_virgin(self):
|
1798
|
+
"""
|
1799
|
+
Mark the database as virgin. This is called by :manage:`prep`.
|
1800
|
+
"""
|
1801
|
+
dbhash = self.get_dbhash()
|
1802
|
+
fn = self.site_dir / "dbhash.json"
|
1803
|
+
with fn.open("w") as fp:
|
1804
|
+
json.dump(dbhash, fp)
|
1805
|
+
# self.site.logger.info("Wrote %s", fn)
|
1806
|
+
|
1807
|
+
def check_virgin(self):
|
1808
|
+
"""
|
1809
|
+
Verify whether the database is virgin. Print the differences if there
|
1810
|
+
are any.
|
1811
|
+
"""
|
1812
|
+
new = self.get_dbhash()
|
1813
|
+
db = self.site_dir
|
1814
|
+
fn = db / "dbhash.json"
|
1815
|
+
if not fn.exists():
|
1816
|
+
raise Exception(
|
1817
|
+
f"No `dbhash.json` in {db} (did you run `django-admin prep`?)")
|
1818
|
+
with fn.open("r") as fp:
|
1819
|
+
old = json.load(fp)
|
1820
|
+
|
1821
|
+
# noi1r has noi1e as master_site, but the react front end removes the
|
1822
|
+
# tinymce plugin, i.e. noi1r doesn't care about
|
1823
|
+
# tinymce.TextFieldTemplate model.
|
1824
|
+
|
1825
|
+
ok = True
|
1826
|
+
for k, v in new.items():
|
1827
|
+
v = set(v)
|
1828
|
+
oldv = set(old.get(k, None))
|
1829
|
+
if oldv != v:
|
1830
|
+
if ok:
|
1831
|
+
print(f"Database {db} isn't virgin:")
|
1832
|
+
ok = False
|
1833
|
+
diffs = []
|
1834
|
+
if (added := len(oldv-v)):
|
1835
|
+
diffs.append(f"{added} rows added")
|
1836
|
+
if (removed := len(v-oldv)):
|
1837
|
+
diffs.append(f"{removed} rows removed")
|
1838
|
+
print(f"- {k}: {', '.join(diffs)}")
|
1839
|
+
|
1840
|
+
def get_dbhash(self):
|
1841
|
+
"""
|
1842
|
+
Return a dictionary with a hash value of the current database content.
|
1843
|
+
"""
|
1844
|
+
rv = dict()
|
1845
|
+
for m in get_models(include_auto_created=True):
|
1846
|
+
k = fmn(m)
|
1847
|
+
if k != "sessions.Session":
|
1848
|
+
# rv[k] = m.objects.count()
|
1849
|
+
rv[k] = list(m.objects.values_list('pk', flat=True))
|
1850
|
+
return rv
|
1851
|
+
|
1799
1852
|
def diagnostic_report_rst(self, *args):
|
1800
1853
|
"""Returns a string with a diagnostic report about this
|
1801
1854
|
site. :manage:`diag` is a command-line shortcut to this.
|
@@ -1992,7 +2045,8 @@ class Site(object):
|
|
1992
2045
|
):
|
1993
2046
|
yield "social_django.middleware.SocialAuthExceptionMiddleware"
|
1994
2047
|
|
1995
|
-
|
2048
|
+
# removed 20240921, see #5755 (Should we remove AjaxExceptionResponse?)
|
2049
|
+
if False:
|
1996
2050
|
yield "lino.utils.ajax.AjaxExceptionResponse"
|
1997
2051
|
|
1998
2052
|
if self.use_security_features:
|
lino/core/tables.py
CHANGED
@@ -637,9 +637,9 @@ method in order to sort the rows of the queryset.
|
|
637
637
|
ba = self.get_action_by_name(an)
|
638
638
|
# ~ print ba
|
639
639
|
if pk is None:
|
640
|
-
ar = self.
|
640
|
+
ar = self.create_request(action=ba)
|
641
641
|
else:
|
642
|
-
ar = self.
|
642
|
+
ar = self.create_request(action=ba, selected_pks=[pk])
|
643
643
|
|
644
644
|
ba.action.run_from_ui(ar)
|
645
645
|
kw = ar.response
|
lino/core/utils.py
CHANGED
@@ -17,7 +17,7 @@ from django.utils.html import format_html, mark_safe, SafeString
|
|
17
17
|
from django.db import models
|
18
18
|
from django.db.models import Q
|
19
19
|
from django.core.exceptions import FieldDoesNotExist
|
20
|
-
from django.utils.functional import lazy
|
20
|
+
# from django.utils.functional import lazy
|
21
21
|
from importlib import import_module
|
22
22
|
from django.utils.translation import gettext as _
|
23
23
|
from django.conf import settings
|
@@ -1046,7 +1046,7 @@ class InstanceAction:
|
|
1046
1046
|
"""
|
1047
1047
|
kwargs.update(selected_rows=[self.instance])
|
1048
1048
|
kwargs.update(parent=ses)
|
1049
|
-
ar = self.bound_action.
|
1049
|
+
ar = self.bound_action.create_request(**kwargs)
|
1050
1050
|
return ar
|
1051
1051
|
|
1052
1052
|
def run_from_session(self, ses, **kwargs):
|
@@ -1070,7 +1070,7 @@ class InstanceAction:
|
|
1070
1070
|
"""
|
1071
1071
|
if len(args) and isinstance(args[0], BaseRequest):
|
1072
1072
|
raise ChangedAPI("20181004")
|
1073
|
-
ar = self.bound_action.
|
1073
|
+
ar = self.bound_action.create_request(
|
1074
1074
|
renderer=settings.SITE.kernel.text_renderer)
|
1075
1075
|
self.run_from_code(ar, *args, **kwargs)
|
1076
1076
|
return ar.response
|
lino/core/views.py
CHANGED
@@ -100,7 +100,7 @@ def action_request(app_label, actor, request, rqdata, is_list, **kw):
|
|
100
100
|
# internationalized because some error handling code
|
101
101
|
# may want to write it to a plain ascii stream.
|
102
102
|
kw.update(renderer=settings.SITE.kernel.default_renderer)
|
103
|
-
ar = rpt.
|
103
|
+
ar = rpt.create_request(request=request, action=a, rqdata=rqdata, **kw)
|
104
104
|
# print("20210403b", a.action.__class__, rqdata)
|
105
105
|
return ar
|
106
106
|
|
@@ -137,7 +137,7 @@ def choices_response(actor, request, qs, row2dict, emptyValue, field=None):
|
|
137
137
|
count = qs.count()
|
138
138
|
|
139
139
|
if offset:
|
140
|
-
qs = qs[int(offset)
|
140
|
+
qs = qs[int(offset):]
|
141
141
|
# ~ kw.update(offset=int(offset))
|
142
142
|
|
143
143
|
if limit:
|
@@ -155,7 +155,7 @@ def choices_response(actor, request, qs, row2dict, emptyValue, field=None):
|
|
155
155
|
row for row in rows if txt in row[constants.CHOICES_TEXT_FIELD].lower()
|
156
156
|
]
|
157
157
|
count = len(rows)
|
158
|
-
rows = rows[int(offset)
|
158
|
+
rows = rows[int(offset):] if offset else rows
|
159
159
|
rows = rows[: int(limit)] if limit else rows
|
160
160
|
|
161
161
|
if wt == constants.WINDOW_TYPE_PARAMS and field and field.blank:
|
lino/help_texts.py
CHANGED
@@ -139,6 +139,7 @@ help_texts = {
|
|
139
139
|
'lino.modlib.extjs.ext_renderer.ExtRenderer.goto_instance' : _("""See JsRenderer.goto_instance(), but when this is called while the detail window is already open (only on another record), then we don’t want to redirect to another page because that would take more time."""),
|
140
140
|
'lino.modlib.extjs.views.AdminIndex' : _("""Similar to PlainIndex"""),
|
141
141
|
'lino.modlib.extjs.views.Restful' : _("""Used to collaborate with a restful Ext.data.Store."""),
|
142
|
+
'lino.modlib.extjs.views.ApiElement' : _("""The view that responds to r'api/(?P<app_label>\w+)/(?P<actor>\w+)/(?P<pk>[^/]+)$'."""),
|
142
143
|
'lino.modlib.gfks.Plugin' : _("""Base class for this plugin."""),
|
143
144
|
'lino.modlib.importfilters.Plugin' : _("""See /dev/plugins."""),
|
144
145
|
'lino.modlib.jinja.Plugin' : _("""See /dev/plugins."""),
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
# Copyright 2009-2023 Rumma & Ko Ltd.
|
3
|
+
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
|
+
|
5
|
+
from click import confirm
|
6
|
+
from django.core.management.base import BaseCommand, CommandError
|
7
|
+
from django.core.management import call_command
|
8
|
+
from django.conf import settings
|
9
|
+
from lino import logger
|
10
|
+
|
11
|
+
|
12
|
+
class Command(BaseCommand):
|
13
|
+
"""Run install, buildcache, collectstatic and makehelp after pull."""
|
14
|
+
|
15
|
+
def add_arguments(self, parser):
|
16
|
+
super().add_arguments(parser)
|
17
|
+
parser.add_argument(
|
18
|
+
"--noinput",
|
19
|
+
action="store_false",
|
20
|
+
dest="interactive",
|
21
|
+
default=True,
|
22
|
+
help="Do not prompt for input of any kind.",
|
23
|
+
),
|
24
|
+
|
25
|
+
def handle(self, *args, **options):
|
26
|
+
interactive = options.get("interactive")
|
27
|
+
verbosity = options.get("verbosity")
|
28
|
+
project_dir = settings.SITE.project_dir
|
29
|
+
|
30
|
+
if interactive:
|
31
|
+
msg = "Build everything for ({})".format(project_dir)
|
32
|
+
msg += ".\nAre you sure?"
|
33
|
+
if not confirm(msg, default=True):
|
34
|
+
raise CommandError("User abort.")
|
35
|
+
|
36
|
+
# the following log message was useful on Travis 20150104
|
37
|
+
if verbosity > 0:
|
38
|
+
logger.info("`buildsite` started on %s.", project_dir)
|
39
|
+
|
40
|
+
pth = project_dir / "settings.py"
|
41
|
+
if pth.exists():
|
42
|
+
pth.touch()
|
43
|
+
|
44
|
+
options = dict(interactive=False, verbosity=verbosity)
|
45
|
+
|
46
|
+
call_command("install", **options)
|
47
|
+
call_command("collectstatic", **options)
|
48
|
+
call_command("buildcache", verbosity=verbosity)
|
49
|
+
if settings.SITE.is_installed("help"):
|
50
|
+
call_command("makehelp", verbosity=verbosity)
|
51
|
+
|
52
|
+
# for p in settings.SITE.installed_plugins:
|
53
|
+
# p.on_buildsite(settings.SITE, verbosity=verbosity)
|
54
|
+
|
55
|
+
settings.SITE.clear_site_config()
|
56
|
+
|
57
|
+
logger.info("`buildsite` finished on %s.", project_dir)
|
@@ -1,7 +1,16 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2009-
|
2
|
+
# Copyright 2009-2025 Rumma & Ko Ltd.
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
|
+
from click import confirm
|
6
|
+
from lino.api import dd
|
7
|
+
from django.db import models
|
8
|
+
from django.db import connections, transaction, DEFAULT_DB_ALIAS
|
9
|
+
from django.core.management.color import no_style
|
10
|
+
from django.db.utils import IntegrityError, OperationalError
|
11
|
+
from django.core.management.base import BaseCommand, CommandError
|
12
|
+
from django.core.management import call_command
|
13
|
+
from django.conf import settings
|
5
14
|
import os
|
6
15
|
import shutil
|
7
16
|
from pathlib import Path
|
@@ -22,20 +31,9 @@ warnings.filterwarnings(
|
|
22
31
|
"django.core.management.commands.loaddata",
|
23
32
|
)
|
24
33
|
|
25
|
-
from django.conf import settings
|
26
|
-
from django.core.management import call_command
|
27
|
-
from django.core.management.base import BaseCommand, CommandError
|
28
|
-
from django.db.utils import IntegrityError, OperationalError
|
29
|
-
from django.db.migrations.exceptions import CircularDependencyError
|
30
|
-
from django.core.management.color import no_style
|
31
34
|
|
32
35
|
# ~ from django.core.management.sql import sql_reset
|
33
|
-
from django.db import connections, transaction, DEFAULT_DB_ALIAS
|
34
|
-
from django.db import models
|
35
|
-
|
36
|
-
from lino.api import dd
|
37
36
|
|
38
|
-
from rstgen.utils import confirm
|
39
37
|
|
40
38
|
USE_SQLDELETE = True
|
41
39
|
|
@@ -198,8 +196,8 @@ class Command(BaseCommand):
|
|
198
196
|
msg = "We are going to flush your database ({})".format(dbname)
|
199
197
|
if removemedia:
|
200
198
|
msg += "\nAND REMOVE ALL FILES BELOW {}".format(mroot)
|
201
|
-
msg += ".\nAre you sure
|
202
|
-
if not confirm(msg):
|
199
|
+
msg += ".\nAre you sure?"
|
200
|
+
if not confirm(msg, default=True):
|
203
201
|
raise CommandError("User abort.")
|
204
202
|
|
205
203
|
# mroot = Path(settings.MEDIA_ROOT)
|
lino/management/commands/prep.py
CHANGED
lino/mixins/sequenced.py
CHANGED
@@ -524,7 +524,7 @@ class Hierarchical(Duplicable):
|
|
524
524
|
et.append(ar.goto_pk(c.id, get_text(c)))
|
525
525
|
i -= 1
|
526
526
|
if child == self:
|
527
|
-
sar = ar.actor.
|
527
|
+
sar = ar.actor.create_request(
|
528
528
|
parent=ar, master_instance=self, is_on_main_actor=False
|
529
529
|
)
|
530
530
|
# sar = ar.spawn_request(master_instance=self, is_on_main_actor=False)
|
lino/modlib/comments/models.py
CHANGED
@@ -257,7 +257,7 @@ class Comment(
|
|
257
257
|
return format_html("<p>{}</p>", s)
|
258
258
|
|
259
259
|
htmls = storypar(self.as_paragraph(ar))
|
260
|
-
for child in RepliesByComment.
|
260
|
+
for child in RepliesByComment.create_request(master_instance=self, parent=ar):
|
261
261
|
htmls += storypar(child.as_story_item(ar, indent=indent + 1))
|
262
262
|
# if self.replies_to_this.count():
|
263
263
|
# # s += "<p>{}</p>".format("Replies:")
|
lino/modlib/comments/ui.py
CHANGED
@@ -129,7 +129,7 @@ class Comments(dd.Table):
|
|
129
129
|
pv = dict(user=user, start_date=sd, end_date=ed,
|
130
130
|
observed_event=CommentEvents.created)
|
131
131
|
# pv = dict(start_date=sd, end_date=ed, observed_event=CommentEvents.created)
|
132
|
-
return cls.
|
132
|
+
return cls.create_request(user=user, param_values=pv)
|
133
133
|
|
134
134
|
# @classmethod
|
135
135
|
# def get_card_title(cls, ar, obj):
|
@@ -302,7 +302,7 @@ class RepliesByComment(CommentsByX):
|
|
302
302
|
|
303
303
|
|
304
304
|
def comments_by_owner(obj):
|
305
|
-
return CommentsByRFC.
|
305
|
+
return CommentsByRFC.create_request(master_instance=obj)
|
306
306
|
|
307
307
|
|
308
308
|
class Reactions(dd.Table):
|
@@ -136,7 +136,7 @@ class ExtRenderer(JsCacheRenderer):
|
|
136
136
|
return self.handler_item(v, js, None)
|
137
137
|
elif v.bound_action is not None:
|
138
138
|
if v.params:
|
139
|
-
ar = v.bound_action.
|
139
|
+
ar = v.bound_action.create_request(**v.params)
|
140
140
|
js = self.request_handler(ar)
|
141
141
|
# print("20230513", js)
|
142
142
|
else:
|
@@ -265,7 +265,7 @@ class ExtRenderer(JsCacheRenderer):
|
|
265
265
|
|
266
266
|
"""
|
267
267
|
if ar is None:
|
268
|
-
sar = ba.
|
268
|
+
sar = ba.create_request(**request_kwargs)
|
269
269
|
else:
|
270
270
|
sar = ar.spawn(ba, **request_kwargs)
|
271
271
|
return self.ar2js(sar, obj, **status)
|