lino 25.1.6__py3-none-any.whl → 25.2.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/core/actions.py +6 -0
- lino/core/actors.py +9 -3
- lino/core/callbacks.py +3 -2
- lino/core/elems.py +1 -1
- lino/core/fields.py +4 -0
- lino/core/keyboard.py +7 -2
- lino/core/model.py +1 -0
- lino/core/requests.py +19 -7
- lino/core/site.py +1 -2
- lino/core/store.py +2 -2
- lino/help_texts.py +3 -1
- lino/locale/bn/LC_MESSAGES/django.po +782 -710
- lino/locale/de/LC_MESSAGES/django.mo +0 -0
- lino/locale/de/LC_MESSAGES/django.po +1259 -1280
- lino/locale/django.pot +751 -702
- lino/locale/es/LC_MESSAGES/django.po +777 -708
- lino/locale/et/LC_MESSAGES/django.po +784 -709
- lino/locale/fr/LC_MESSAGES/django.po +1339 -1191
- lino/locale/nl/LC_MESSAGES/django.po +787 -712
- lino/locale/pt_BR/LC_MESSAGES/django.po +769 -700
- lino/locale/zh_Hant/LC_MESSAGES/django.po +769 -700
- lino/management/commands/demotest.py +2 -1
- lino/mixins/__init__.py +1 -1
- lino/modlib/checkdata/choicelists.py +5 -4
- lino/modlib/checkdata/models.py +9 -8
- lino/modlib/help/models.py +5 -0
- lino/modlib/jinja/__init__.py +0 -4
- lino/modlib/memo/__init__.py +1 -1
- lino/modlib/notify/mixins.py +6 -8
- lino/modlib/periods/mixins.py +1 -25
- lino/modlib/periods/models.py +42 -9
- lino/modlib/system/choicelists.py +12 -11
- lino/modlib/uploads/fixtures/demo.py +1 -1
- lino/modlib/uploads/models.py +2 -1
- lino/utils/config.py +2 -0
- lino/utils/dpy.py +15 -3
- lino/utils/soup.py +136 -103
- {lino-25.1.6.dist-info → lino-25.2.1.dist-info}/METADATA +1 -1
- {lino-25.1.6.dist-info → lino-25.2.1.dist-info}/RECORD +43 -43
- {lino-25.1.6.dist-info → lino-25.2.1.dist-info}/WHEEL +0 -0
- {lino-25.1.6.dist-info → lino-25.2.1.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.1.6.dist-info → lino-25.2.1.dist-info}/licenses/COPYING +0 -0
lino/__init__.py
CHANGED
lino/core/actions.py
CHANGED
@@ -1069,6 +1069,9 @@ class CreateRow(Action):
|
|
1069
1069
|
|
1070
1070
|
# select_rows = False
|
1071
1071
|
def run_from_ui(self, ar, **kwargs):
|
1072
|
+
if (msg := ar.actor.model.disable_create(ar)) is not None:
|
1073
|
+
ar.error(msg)
|
1074
|
+
return
|
1072
1075
|
elem = ar.create_instance_from_request(**kwargs)
|
1073
1076
|
self.save_new_instance(ar, elem)
|
1074
1077
|
|
@@ -1140,6 +1143,9 @@ class SubmitInsert(CreateRow):
|
|
1140
1143
|
# button actions would try to refer the requesting panel which
|
1141
1144
|
# is going to be closed (this disturbs at least in ticket
|
1142
1145
|
# #219)
|
1146
|
+
if (msg := ar.actor.model.disable_create(ar)) is not None:
|
1147
|
+
ar.error(msg)
|
1148
|
+
return
|
1143
1149
|
ar.requesting_panel = None
|
1144
1150
|
|
1145
1151
|
if ar.actor.handle_uploaded_files is not None:
|
lino/core/actors.py
CHANGED
@@ -975,10 +975,16 @@ class Actor(actions.Parametrizable, Permittable, metaclass=ActorMetaClass):
|
|
975
975
|
|
976
976
|
@classmethod
|
977
977
|
def get_create_permission(self, ar):
|
978
|
-
if not
|
979
|
-
return
|
980
|
-
if
|
978
|
+
if not self.allow_create:
|
979
|
+
return False
|
980
|
+
if settings.SITE.readonly:
|
981
981
|
return False
|
982
|
+
if settings.SITE.user_types_module:
|
983
|
+
user = ar.get_user()
|
984
|
+
if user.user_type.readonly:
|
985
|
+
return False
|
986
|
+
if self.hide_editing(user.user_type):
|
987
|
+
return False
|
982
988
|
return True
|
983
989
|
|
984
990
|
@classmethod
|
lino/core/callbacks.py
CHANGED
@@ -52,9 +52,10 @@ class Callback(object):
|
|
52
52
|
self.choices_dict = {}
|
53
53
|
self.ar = ar
|
54
54
|
|
55
|
-
str_msg =
|
55
|
+
str_msg = f"{ar.get_user().username}:{tostring(message)}"
|
56
|
+
|
56
57
|
# self.uid = uid if uid is not None else str(md5(str_msg).digest())
|
57
|
-
self.uid = uid if uid is not None else md5(str_msg).hexdigest()
|
58
|
+
self.uid = uid if uid is not None else md5(str_msg.encode()).hexdigest()
|
58
59
|
# 20240407 .digest() returned bytestrings, yielding strings of style
|
59
60
|
# "b'8\x04\xeb\xf53\x9f\xf2\x90\x82l\x81~s\xe8\x90\xa6'"
|
60
61
|
|
lino/core/elems.py
CHANGED
@@ -1090,7 +1090,7 @@ class ForeignKeyElement(ComplexRemoteComboFieldElement):
|
|
1090
1090
|
options = dict(
|
1091
1091
|
related_actor_id=actor.actor_id, allowBlank=kw.get("allowBlank", False)
|
1092
1092
|
)
|
1093
|
-
da = actor.
|
1093
|
+
da = actor.detail_action
|
1094
1094
|
options.update(
|
1095
1095
|
view_permission=bool(da) and da.get_view_permission(get_user_profile())
|
1096
1096
|
)
|
lino/core/fields.py
CHANGED
@@ -1299,6 +1299,10 @@ class TableRow(object):
|
|
1299
1299
|
# return v
|
1300
1300
|
# raise Exception("Oops, {} on {} is {}".format(name, cls, v))
|
1301
1301
|
|
1302
|
+
@classmethod
|
1303
|
+
def disable_create(self, ar):
|
1304
|
+
return None
|
1305
|
+
|
1302
1306
|
def get_detail_action(self, ar):
|
1303
1307
|
"""Return the (bound) detail action to use for showing this object in
|
1304
1308
|
a detail window. Return `None` when no detail form exists or
|
lino/core/keyboard.py
CHANGED
@@ -6,6 +6,12 @@ This defines the :class:`Hotkey` class and some keystrokes.
|
|
6
6
|
|
7
7
|
The system is not yet heavily used.
|
8
8
|
|
9
|
+
React uses the attributes `ctrl`, `shift`, `alt` and `code`.
|
10
|
+
|
11
|
+
For the `code`, see:
|
12
|
+
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code
|
13
|
+
|
14
|
+
|
9
15
|
"""
|
10
16
|
|
11
17
|
|
@@ -23,7 +29,7 @@ class Hotkey(object):
|
|
23
29
|
if key:
|
24
30
|
self.key = key.upper()
|
25
31
|
self.keycode = ord(self.key)
|
26
|
-
for k, v in
|
32
|
+
for k, v in kw.items():
|
27
33
|
setattr(self, k, v)
|
28
34
|
|
29
35
|
self.__dict__.update(
|
@@ -35,7 +41,6 @@ class Hotkey(object):
|
|
35
41
|
alt=self.alt,
|
36
42
|
)
|
37
43
|
|
38
|
-
|
39
44
|
# ExtJS src/core/EventManager-more.js
|
40
45
|
RETURN = Hotkey(keycode=13, code="Enter")
|
41
46
|
ESCAPE = Hotkey(keycode=27, code="Escape")
|
lino/core/model.py
CHANGED
lino/core/requests.py
CHANGED
@@ -102,6 +102,7 @@ def mi2bp(master_instance, bp):
|
|
102
102
|
# raise Exception("No master key for {} {!r}".format(
|
103
103
|
# self.master_instance.__class__, self.master_instance))
|
104
104
|
|
105
|
+
|
105
106
|
class StringLogger(logging.Logger):
|
106
107
|
# Instantiated by BaseRequest.capture_logger()
|
107
108
|
|
@@ -542,6 +543,17 @@ class BaseRequest:
|
|
542
543
|
self.logger.streamer.flush()
|
543
544
|
self.logger = old_logger
|
544
545
|
|
546
|
+
@contextmanager
|
547
|
+
def override_attrs(self, **kwargs):
|
548
|
+
old_values = {k: getattr(self, k) for k in kwargs.keys()}
|
549
|
+
for k, v in kwargs.items():
|
550
|
+
setattr(self, k, v)
|
551
|
+
try:
|
552
|
+
yield
|
553
|
+
finally:
|
554
|
+
for k, v in old_values.items():
|
555
|
+
setattr(self, k, v)
|
556
|
+
|
545
557
|
def get_row_classes(self, row):
|
546
558
|
if self.actor is None or self.actor.get_row_classes is None:
|
547
559
|
return
|
@@ -2061,20 +2073,20 @@ class ActionRequest(BaseRequest):
|
|
2061
2073
|
return
|
2062
2074
|
# if self.actor.insert_layout is not None: # and not self.actor.stay_in_grid \
|
2063
2075
|
# return
|
2064
|
-
if
|
2065
|
-
self.create_kw is None
|
2066
|
-
or self.actor.hide_editing(self.get_user().user_type)
|
2067
|
-
or not self.actor.allow_create
|
2068
|
-
):
|
2076
|
+
if self.create_kw is None:
|
2077
|
+
# print("20250127 self.create_kw is None")
|
2069
2078
|
return
|
2070
2079
|
if not self.actor.get_create_permission(self):
|
2071
2080
|
return
|
2081
|
+
# raise Exception("20250127 create_phantom_rows")
|
2082
|
+
if self.actor.model is not None:
|
2083
|
+
if self.actor.model.disable_create(self) is not None:
|
2084
|
+
return
|
2072
2085
|
yield PhantomRow(self, **kw)
|
2073
2086
|
|
2074
2087
|
def create_instance(self, **kw):
|
2075
2088
|
"""
|
2076
|
-
Create a row
|
2077
|
-
the specified keyword arguments.
|
2089
|
+
Create a database row using the specified keyword arguments.
|
2078
2090
|
"""
|
2079
2091
|
if self.create_kw:
|
2080
2092
|
kw.update(self.create_kw)
|
lino/core/site.py
CHANGED
lino/core/store.py
CHANGED
@@ -576,11 +576,11 @@ class DisabledFieldsStoreField(SpecialStoreField):
|
|
576
576
|
|
577
577
|
"""
|
578
578
|
|
579
|
-
name =
|
579
|
+
name = "disabled_fields"
|
580
580
|
|
581
581
|
def __init__(self, store):
|
582
582
|
# from lino.core.gfks import GenericForeignKey
|
583
|
-
|
583
|
+
super().__init__(store)
|
584
584
|
self.always_disabled = set()
|
585
585
|
for f in self.store.all_fields:
|
586
586
|
if f.field is not None:
|
lino/help_texts.py
CHANGED
@@ -8,7 +8,7 @@ help_texts = {
|
|
8
8
|
'lino.mixins.Contactable' : _("""Mixin for models that represent somebody who can be contacted by email."""),
|
9
9
|
'lino.mixins.Contactable.get_as_user' : _("""Return the user object representing this contactable."""),
|
10
10
|
'lino.mixins.Phonable' : _("""Mixin for models that represent somebody who can be contacted by phone."""),
|
11
|
-
'lino.mixins.Modified' : _("""Adds a a timestamp field
|
11
|
+
'lino.mixins.Modified' : _("""Adds a a timestamp field that holds the last modification time of every individual database object."""),
|
12
12
|
'lino.mixins.Modified.modified' : _("""The time when this database object was last modified."""),
|
13
13
|
'lino.mixins.Modified.auto_touch' : _("""Whether to touch objects automatically when saving them."""),
|
14
14
|
'lino.mixins.Created' : _("""Adds a timestamp field which holds the creation time of every individual database object."""),
|
@@ -315,6 +315,7 @@ help_texts = {
|
|
315
315
|
'lino.utils.ucsv.UTF8Recoder' : _("""Iterator that reads an encoded stream and reencodes the input to UTF-8"""),
|
316
316
|
'lino.utils.ucsv.UnicodeReader' : _("""A CSV reader which will iterate over lines in the CSV file “f”, which is encoded in the given encoding."""),
|
317
317
|
'lino.utils.ucsv.UnicodeWriter' : _("""A CSV writer which will write rows to CSV file “f”, which is encoded in the given encoding."""),
|
318
|
+
'lino.core.model.Model.disable_create' : _("""Return a veto message if you want to refuse creating rows on this model in the given action request even when permission has been given."""),
|
318
319
|
'lino.core.model.Model.on_create' : _("""Override this to set default values that depend on the request."""),
|
319
320
|
'lino.core.model.Model.after_ui_create' : _("""Hook to define custom behaviour to run when a user has created a new instance of this model."""),
|
320
321
|
'lino.core.model.Model.submit_insert' : _("""The SubmitInsert action to be executed when the when the users submits an insert window."""),
|
@@ -354,6 +355,7 @@ help_texts = {
|
|
354
355
|
'lino.modlib.checkdata.Checkers' : _("""The list of data checkers known by this application."""),
|
355
356
|
'lino.modlib.checkdata.Checker' : _("""Base class for all data checkers."""),
|
356
357
|
'lino.modlib.checkdata.Checker.model' : _("""The model to be checked. If this is a string, Lino will resolve it at startup."""),
|
358
|
+
'lino.modlib.checkdata.Checker.no_auto' : _("""Whether this checker should be ignored by checkdata."""),
|
357
359
|
'lino.modlib.checkdata.Checker.check_instance' : _("""Run get_checkdata_problems() on this checker for the given database object."""),
|
358
360
|
'lino.modlib.checkdata.Checker.get_checkable_models' : _("""Return a list of the models to check."""),
|
359
361
|
'lino.modlib.checkdata.Checker.activate' : _("""Creates an instance of this class and adds it as a choice to the Checkers choicelist."""),
|