lino 25.4.4__py3-none-any.whl → 25.4.5__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/fields.py +4 -2
- lino/core/kernel.py +4 -1
- lino/core/requests.py +1 -1
- lino/core/site.py +52 -45
- lino/core/utils.py +7 -2
- lino/help_texts.py +0 -2
- lino/mixins/registrable.py +5 -4
- lino/modlib/jinja/mixins.py +2 -0
- lino/modlib/linod/management/commands/linod.py +5 -20
- lino/modlib/linod/mixins.py +0 -39
- lino/modlib/publisher/config/publisher/page.pub.html +6 -0
- lino/modlib/publisher/fixtures/synodalworld.py +14 -1
- lino/modlib/publisher/models.py +16 -12
- lino/utils/__init__.py +1 -56
- lino/utils/sums.py +75 -0
- {lino-25.4.4.dist-info → lino-25.4.5.dist-info}/METADATA +1 -1
- {lino-25.4.4.dist-info → lino-25.4.5.dist-info}/RECORD +21 -20
- {lino-25.4.4.dist-info → lino-25.4.5.dist-info}/WHEEL +0 -0
- {lino-25.4.4.dist-info → lino-25.4.5.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.4.4.dist-info → lino-25.4.5.dist-info}/licenses/COPYING +0 -0
lino/__init__.py
CHANGED
@@ -31,7 +31,7 @@ from django import VERSION
|
|
31
31
|
from django.apps import AppConfig
|
32
32
|
from django.conf import settings
|
33
33
|
import warnings
|
34
|
-
__version__ = '25.4.
|
34
|
+
__version__ = '25.4.5'
|
35
35
|
|
36
36
|
# import setuptools # avoid UserWarning "Distutils was imported before Setuptools"?
|
37
37
|
|
lino/core/fields.py
CHANGED
@@ -163,7 +163,7 @@ class PriceField(models.DecimalField):
|
|
163
163
|
"""
|
164
164
|
A thin wrapper around Django's `DecimalField
|
165
165
|
<https://docs.djangoproject.com/en/5.0/ref/models/fields/#decimalfield>`_
|
166
|
-
|
166
|
+
with price-like default values for `decimal_places`, `max_length` and
|
167
167
|
`max_digits`.
|
168
168
|
"""
|
169
169
|
|
@@ -656,8 +656,10 @@ class VirtualField(FakeField):
|
|
656
656
|
self.model = model
|
657
657
|
self.name = name
|
658
658
|
self.attname = name
|
659
|
+
# if getattr(self.return_type, "model", False):
|
659
660
|
if hasattr(self.return_type, "model"):
|
660
|
-
# logger.info("20200425 return_type for virtual
|
661
|
+
# logger.info("20200425 return_type for virtual "
|
662
|
+
# "field %s has a model %s (not %s)", self, self.return_type.model, model)
|
661
663
|
return
|
662
664
|
self.return_type.model = VirtualModel(model)
|
663
665
|
self.return_type.column = None
|
lino/core/kernel.py
CHANGED
@@ -37,6 +37,7 @@ from django.utils.translation import gettext_lazy as _
|
|
37
37
|
from django.core.exceptions import PermissionDenied, ValidationError
|
38
38
|
from django.db.utils import DatabaseError
|
39
39
|
from django.db import IntegrityError
|
40
|
+
from django.utils.log import DEFAULT_LOGGING
|
40
41
|
|
41
42
|
from django.db import models
|
42
43
|
|
@@ -162,7 +163,9 @@ class Kernel(object):
|
|
162
163
|
# logger.info("20231016 kernel_startup (%s)", site._history_aware_logging)
|
163
164
|
# print("20231019 kernel_startup()", site, site._history_aware_logging)
|
164
165
|
|
165
|
-
if site._history_aware_logging:
|
166
|
+
# if site._history_aware_logging:
|
167
|
+
# if not is_devserver():
|
168
|
+
if "file" in DEFAULT_LOGGING['handlers']:
|
166
169
|
if len(sys.argv) == 0:
|
167
170
|
process_name = "WSGI"
|
168
171
|
else:
|
lino/core/requests.py
CHANGED
@@ -2031,9 +2031,9 @@ class ActionRequest(BaseRequest):
|
|
2031
2031
|
if w is None:
|
2032
2032
|
WARNINGS_LOGGED[e] = True
|
2033
2033
|
# raise
|
2034
|
-
# logger.exception(e)
|
2035
2034
|
logger.warning(f"Error while executing {repr(self)}: {e}\n"
|
2036
2035
|
"(Subsequent warnings will be silenced.)")
|
2036
|
+
logger.exception(e)
|
2037
2037
|
|
2038
2038
|
if self._data_iterator is None:
|
2039
2039
|
raise Exception(f"No data iterator for {self}")
|
lino/core/site.py
CHANGED
@@ -36,12 +36,13 @@ from lino.utils.html import E, tostring
|
|
36
36
|
from lino.core.plugin import Plugin
|
37
37
|
from lino.utils import AttrDict, date_offset, i2d, buildurl
|
38
38
|
|
39
|
+
|
39
40
|
NO_REMOTE_AUTH = True
|
40
41
|
# 20240518 We have only one production site still using remote http
|
41
42
|
# authentication, and they will migrate to sessions-based auth with their next
|
42
43
|
# upgrade.
|
43
44
|
|
44
|
-
ASYNC_LOGGING = False
|
45
|
+
# ASYNC_LOGGING = False
|
45
46
|
# This is to fix the issue that the "started" and "ended" messages are not logged.
|
46
47
|
# But setting this to True causes #4986 (Unable to configure handler 'mail_admins')
|
47
48
|
# because since 20230529 we called logging..config.dictConfig() during
|
@@ -368,14 +369,14 @@ class Site(object):
|
|
368
369
|
csv_params = dict()
|
369
370
|
|
370
371
|
# attributes documented in book/docs/opics/loggin.rst:
|
371
|
-
_history_aware_logging =
|
372
|
+
_history_aware_logging = True
|
372
373
|
log_each_action_request = False
|
374
|
+
default_loglevel = "INFO"
|
373
375
|
logger_filename = "lino.log"
|
374
376
|
logger_format = (
|
375
377
|
"%(asctime)s %(levelname)s [%(name)s %(process)d %(thread)d] : %(message)s"
|
376
378
|
)
|
377
379
|
auto_configure_logger_names = "atelier lino"
|
378
|
-
log_sock_path = None
|
379
380
|
|
380
381
|
# appy_params = dict(ooPort=8100)
|
381
382
|
appy_params = dict(
|
@@ -597,31 +598,36 @@ class Site(object):
|
|
597
598
|
self.startup_time = datetime.datetime.now()
|
598
599
|
|
599
600
|
def setup_logging(self):
|
600
|
-
# documented in book/docs/
|
601
|
+
# documented in book/docs/topics/logging.rst
|
601
602
|
|
602
|
-
if
|
603
|
+
if self.auto_configure_logger_names is None:
|
603
604
|
return
|
604
605
|
|
605
|
-
if len(logging.root.handlers) > 0:
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
606
|
+
# if len(logging.root.handlers) > 0:
|
607
|
+
#
|
608
|
+
# # Logging has been configured by something else. This can happen
|
609
|
+
# # when Site is instantiated a second time. Or accidentaly (e.g. when
|
610
|
+
# # you call logging.basicConfig() in the settings.py), Or when some
|
611
|
+
# # testing environment runs multiple doctests in a same process. We
|
612
|
+
# # don't care, we restart configuration from scratch.
|
613
|
+
#
|
614
|
+
# for handler in logging.root.handlers[:]:
|
615
|
+
# logging.root.removeHandler(handler)
|
613
616
|
|
614
617
|
from django.utils.log import DEFAULT_LOGGING
|
615
618
|
|
616
619
|
d = DEFAULT_LOGGING
|
617
620
|
|
618
|
-
if d.get("logger_ok", False):
|
619
|
-
|
620
|
-
|
621
|
+
# if d.get("logger_ok", False):
|
622
|
+
# # raise Exception("20231017")
|
623
|
+
# return
|
621
624
|
|
622
|
-
level = os.environ.get("LINO_LOGLEVEL",
|
625
|
+
level = os.environ.get("LINO_LOGLEVEL", self.default_loglevel).upper()
|
623
626
|
file_level = os.environ.get("LINO_FILE_LOGLEVEL", level).upper()
|
624
|
-
|
627
|
+
sql_level = os.environ.get("LINO_SQL_LOGLEVEL", level).upper()
|
628
|
+
|
629
|
+
min_level = min(*[getattr(logging, k) for k in (
|
630
|
+
level, file_level, sql_level)])
|
625
631
|
|
626
632
|
# print("20231017 level is", level)
|
627
633
|
|
@@ -642,22 +648,13 @@ class Site(object):
|
|
642
648
|
|
643
649
|
# when Site is instantiated several times, we keep the existing file handler
|
644
650
|
# print("20231016", self.logger_filename, handlers.keys())
|
645
|
-
if
|
651
|
+
if "file" not in handlers:
|
646
652
|
logdir = self.site_dir / "log"
|
647
653
|
if logdir.is_dir():
|
648
654
|
self._history_aware_logging = True
|
649
655
|
log_file_path = logdir / self.logger_filename
|
650
656
|
# print("20231019 logging", file_level, "to", log_file_path)
|
651
|
-
|
652
|
-
if self.log_sock_path.exists():
|
653
|
-
# print("20231019 log via socket server")
|
654
|
-
handlers["file"] = {
|
655
|
-
"class": "lino.core.site.LinoSocketHandler",
|
656
|
-
"host": str(self.log_sock_path),
|
657
|
-
"port": None,
|
658
|
-
"level": file_level,
|
659
|
-
}
|
660
|
-
else:
|
657
|
+
if True:
|
661
658
|
# print("20231019 log directly to file")
|
662
659
|
formatters = d.setdefault("formatters", {})
|
663
660
|
formatters.setdefault(
|
@@ -671,6 +668,15 @@ class Site(object):
|
|
671
668
|
"encoding": "UTF-8",
|
672
669
|
"formatter": "verbose",
|
673
670
|
}
|
671
|
+
else:
|
672
|
+
try:
|
673
|
+
from systemd.journal import JournalHandler
|
674
|
+
handlers["file"] = {
|
675
|
+
"class": "systemd.journal.JournalHandler",
|
676
|
+
"SYSLOG_IDENTIFIER": str(self.project_name),
|
677
|
+
}
|
678
|
+
except ImportError:
|
679
|
+
pass
|
674
680
|
|
675
681
|
# when a file handler exists, we have the loggers use it even if this
|
676
682
|
# instance didn't create it:
|
@@ -681,9 +687,10 @@ class Site(object):
|
|
681
687
|
# if name not in d['loggers']:
|
682
688
|
d["loggers"][name] = loggercfg
|
683
689
|
|
684
|
-
|
685
|
-
|
686
|
-
|
690
|
+
if sql_level != level:
|
691
|
+
dblogger = d["loggers"].setdefault("django.db.backends", {})
|
692
|
+
dblogger["level"] = sql_level
|
693
|
+
dblogger["handlers"] = loggercfg["handlers"]
|
687
694
|
|
688
695
|
# # https://code.djangoproject.com/ticket/30554
|
689
696
|
# logger = d['loggers'].setdefault('django.utils.autoreload', {})
|
@@ -694,19 +701,19 @@ class Site(object):
|
|
694
701
|
# if item not in ['linod', 'root']:
|
695
702
|
# d['loggers'][item]['propagate'] = True
|
696
703
|
|
697
|
-
if ASYNC_LOGGING:
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
else:
|
709
|
-
|
704
|
+
# if ASYNC_LOGGING:
|
705
|
+
# config = d.copy()
|
706
|
+
#
|
707
|
+
# try:
|
708
|
+
# logging.config.dictConfig(config)
|
709
|
+
# # logging.config.dictConfig(d)
|
710
|
+
# finally:
|
711
|
+
# d.clear()
|
712
|
+
# # d["logger_ok"] = True
|
713
|
+
# d["version"] = 1
|
714
|
+
# d["disable_existing_loggers"] = False
|
715
|
+
# else:
|
716
|
+
# d["logger_ok"] = True
|
710
717
|
# self.update_settings(LOGGING=d)
|
711
718
|
# pprint(d)
|
712
719
|
# print("20161126 Site %s " % d['loggers'].keys())
|
lino/core/utils.py
CHANGED
@@ -37,6 +37,9 @@ get_models = apps.get_models
|
|
37
37
|
|
38
38
|
validate_url = URLValidator()
|
39
39
|
|
40
|
+
DEVSERVER_COMMANDS = {
|
41
|
+
"runserver", "testserver", "test", "demotest", "makescreenshots", "shell"}
|
42
|
+
|
40
43
|
|
41
44
|
def djangoname(o):
|
42
45
|
return o.__module__.split(".")[-2] + "." + o.__name__
|
@@ -144,6 +147,8 @@ def is_devserver():
|
|
144
147
|
|
145
148
|
"""
|
146
149
|
# ~ print 20130315, sys.argv[1]
|
150
|
+
if settings.DEBUG:
|
151
|
+
return True # doctest under pytest
|
147
152
|
if sys.argv[0].startswith("-"):
|
148
153
|
return True # doctest under pytest
|
149
154
|
if len(sys.argv) <= 1:
|
@@ -153,9 +158,9 @@ def is_devserver():
|
|
153
158
|
# if sys.argv[0].endswith("doctest.py") or sys.argv[0].endswith("doctest_utf8.py"):
|
154
159
|
if sys.argv[0].endswith("doctest.py") or sys.argv[0].endswith("pytest"):
|
155
160
|
return True
|
156
|
-
if sys.argv[1] in
|
161
|
+
if sys.argv[1] in DEVSERVER_COMMANDS:
|
157
162
|
return True
|
158
|
-
# print(sys.argv
|
163
|
+
# print(sys.argv)
|
159
164
|
return False
|
160
165
|
|
161
166
|
|
lino/help_texts.py
CHANGED
@@ -182,8 +182,6 @@ help_texts = {
|
|
182
182
|
'lino.utils.IncompleteDate' : _("""Naive representation of a potentially incomplete gregorian date."""),
|
183
183
|
'lino.utils.IncompleteDate.parse' : _("""Parse the given string and return an IncompleteDate object."""),
|
184
184
|
'lino.utils.IncompleteDate.get_age' : _("""Return age in years as integer."""),
|
185
|
-
'lino.utils.SumCollector' : _("""A dictionary of sums to be collected using an arbitrary key."""),
|
186
|
-
'lino.utils.SumCollector.collect' : _("""Add the given value to the sum at the given key k."""),
|
187
185
|
'lino.utils.MissingRow' : _("""Represents a database row that is expected to exist but doesn’t."""),
|
188
186
|
'lino.utils.addressable.Addressable' : _("""General mixin (not only for Django models) to encapsulate the generating of “traditional” (“snail”) mail addresses."""),
|
189
187
|
'lino.utils.addressable.Addressable.address_person_lines' : _("""Yield one or more text lines, one for each line of the person part."""),
|
lino/mixins/registrable.py
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2010-
|
2
|
+
# Copyright 2010-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
"""
|
5
5
|
This defines the :class:`Registable` model mixin.
|
6
6
|
"""
|
7
7
|
|
8
8
|
from django.db import models
|
9
|
-
from django.utils.translation import gettext_lazy as _
|
9
|
+
# from django.utils.translation import gettext_lazy as _
|
10
10
|
|
11
|
+
from lino import logger
|
11
12
|
from lino.core import model
|
12
|
-
from lino.core.actions import Action
|
13
|
+
# from lino.core.actions import Action
|
13
14
|
from lino.core.workflows import ChangeStateAction
|
14
15
|
from lino.core.exceptions import ChangedAPI
|
15
|
-
|
16
16
|
from lino.core.workflows import State
|
17
17
|
|
18
18
|
|
@@ -180,6 +180,7 @@ class Registrable(model.Model):
|
|
180
180
|
state_field = self.workflow_state_field
|
181
181
|
target_state = state_field.choicelist.draft
|
182
182
|
self.set_workflow_state(ar, state_field, target_state)
|
183
|
+
logger.warning("%s deregisters %s", ar.get_user(), self)
|
183
184
|
|
184
185
|
# no longer needed after 20170826
|
185
186
|
# @classmethod
|
lino/modlib/jinja/mixins.py
CHANGED
@@ -11,6 +11,7 @@ from django.conf import settings
|
|
11
11
|
from django.utils.html import mark_safe, escape
|
12
12
|
|
13
13
|
from lino.api import dd, _
|
14
|
+
from lino.utils.sums import myround
|
14
15
|
from lino.utils.xml import validate_xml
|
15
16
|
from lino.utils.media import MediaFile
|
16
17
|
|
@@ -51,6 +52,7 @@ class XMLMaker(dd.Model):
|
|
51
52
|
context = self.get_printable_context(ar)
|
52
53
|
context.update(xml_element=xml_element)
|
53
54
|
context.update(base64=base64)
|
55
|
+
context.update(myround=myround)
|
54
56
|
xml = tpl.render(**context)
|
55
57
|
# parts = [
|
56
58
|
# dd.plugins.accounting.xml_media_dir,
|
@@ -3,13 +3,11 @@
|
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
5
|
# import time
|
6
|
-
import os
|
7
6
|
import asyncio
|
8
|
-
|
9
7
|
from django.conf import settings
|
10
8
|
from django.core.management import BaseCommand, call_command
|
11
|
-
from lino.api import dd
|
12
|
-
from lino.modlib.linod.mixins import
|
9
|
+
from lino.api import dd
|
10
|
+
from lino.modlib.linod.mixins import start_task_runner
|
13
11
|
from lino.core.requests import BaseRequest
|
14
12
|
|
15
13
|
if dd.plugins.linod.use_channels:
|
@@ -33,19 +31,6 @@ class Command(BaseCommand):
|
|
33
31
|
# default=False)
|
34
32
|
|
35
33
|
def handle(self, *args, **options):
|
36
|
-
log_sock_path = settings.SITE.log_sock_path
|
37
|
-
|
38
|
-
if log_sock_path and log_sock_path.exists():
|
39
|
-
if options.get("force"):
|
40
|
-
log_sock_path.unlink()
|
41
|
-
else:
|
42
|
-
raise Exception(
|
43
|
-
f"log socket already exists: {log_sock_path}\n"
|
44
|
-
"It's probable that a worker process is already running. "
|
45
|
-
"Try: 'ps awx | grep linod' OR 'sudo supervisorctl status | grep worker'\n"
|
46
|
-
"Or the last instance of the worker process did not finish properly. "
|
47
|
-
"In that case remove the file and run this command again."
|
48
|
-
)
|
49
34
|
|
50
35
|
if not dd.plugins.linod.use_channels:
|
51
36
|
# print("20240424 Run Lino daemon without channels")
|
@@ -57,8 +42,8 @@ class Command(BaseCommand):
|
|
57
42
|
except settings.SITE.user_model.DoesNotExist:
|
58
43
|
u = None
|
59
44
|
ar = BaseRequest(user=u)
|
60
|
-
#
|
61
|
-
await
|
45
|
+
# await asyncio.gather(start_log_server(), start_task_runner(ar))
|
46
|
+
await start_task_runner(ar)
|
62
47
|
# t1 = asyncio.create_task(settings.SITE.start_log_server())
|
63
48
|
# t2 = asyncio.create_task(start_task_runner(ar))
|
64
49
|
# await t1
|
@@ -84,7 +69,7 @@ class Command(BaseCommand):
|
|
84
69
|
async def initiate_linod():
|
85
70
|
layer = get_channel_layer()
|
86
71
|
# if log_sock_path is not None:
|
87
|
-
await layer.send(CHANNEL_NAME, {"type": "log.server"})
|
72
|
+
# await layer.send(CHANNEL_NAME, {"type": "log.server"})
|
88
73
|
# await asyncio.sleep(1)
|
89
74
|
await layer.send(CHANNEL_NAME, {"type": "run.background.tasks"})
|
90
75
|
|
lino/modlib/linod/mixins.py
CHANGED
@@ -291,42 +291,3 @@ async def start_task_runner(ar=None, max_count=None):
|
|
291
291
|
continue
|
292
292
|
await ar.adebug("Let task runner sleep for %s seconds.", to_sleep)
|
293
293
|
await asyncio.sleep(to_sleep)
|
294
|
-
|
295
|
-
|
296
|
-
class LogReceiver(asyncio.Protocol):
|
297
|
-
# def connection_made(self, transport):
|
298
|
-
# print("20231019 connection_made", transport)
|
299
|
-
|
300
|
-
def data_received(self, data: bytes):
|
301
|
-
data = pickle.loads(
|
302
|
-
data[4:]
|
303
|
-
) # first four bytes gives the size of the rest of the data
|
304
|
-
record = logging.makeLogRecord(data)
|
305
|
-
# print("20231019 data_received", record)
|
306
|
-
# 20231019 server_logger.handle(record)
|
307
|
-
logger.handle(record)
|
308
|
-
|
309
|
-
|
310
|
-
async def start_log_server():
|
311
|
-
# 'log.server' in linod.py
|
312
|
-
site = settings.SITE
|
313
|
-
log_sock_path = site.log_sock_path
|
314
|
-
if log_sock_path is None:
|
315
|
-
logger.info(
|
316
|
-
"No log server because there is no directory %s.", site.site_dir / "log"
|
317
|
-
)
|
318
|
-
return
|
319
|
-
if log_sock_path.exists():
|
320
|
-
raise Exception("Cannot start log server when socket file exists.")
|
321
|
-
logger.info("Log server starts listening on %s", log_sock_path)
|
322
|
-
|
323
|
-
def remove_sock_file():
|
324
|
-
logger.info("Remove socket file %s", site.log_sock_path)
|
325
|
-
site.log_sock_path.unlink(missing_ok=True)
|
326
|
-
|
327
|
-
site.register_shutdown_task(remove_sock_file)
|
328
|
-
loop = asyncio.get_running_loop()
|
329
|
-
server = await loop.create_unix_server(LogReceiver, log_sock_path)
|
330
|
-
# await server.serve_forever()
|
331
|
-
async with server:
|
332
|
-
await server.serve_forever()
|
@@ -6,6 +6,12 @@
|
|
6
6
|
{% if isinstance(obj, rt.models.publisher.Page) -%}
|
7
7
|
{{obj.get_prev_link(ar)}} | {{obj.get_next_link(ar)}} |
|
8
8
|
{% endif -%}
|
9
|
+
{% if dd.is_installed('react') %}
|
10
|
+
{% set ar_react = obj.get_default_table().request(parent=ar, permalink_uris=True, renderer=dd.plugins.react.renderer) %}
|
11
|
+
{% if ar_react.obj2url(obj) %}
|
12
|
+
{{ tostring(ar_react.obj2html(obj, text='Edit')) }} |
|
13
|
+
{% endif %}
|
14
|
+
{% endif %}
|
9
15
|
{% if ar.request and ar.request.path != '/' -%}
|
10
16
|
<a href="{{ar.get_home_url()}}">{{_("Home")}}</a>
|
11
17
|
{% else -%}
|
@@ -14,4 +14,17 @@ home_children = [
|
|
14
14
|
|
15
15
|
|
16
16
|
def objects():
|
17
|
-
|
17
|
+
image = rt.models.uploads.Upload.objects.first()
|
18
|
+
print('='*80)
|
19
|
+
print(image)
|
20
|
+
def iterate(iterable):
|
21
|
+
try:
|
22
|
+
for obj in iterable:
|
23
|
+
yield iterate(obj)
|
24
|
+
except TypeError:
|
25
|
+
if (obj := iterable).title == 'Mission':
|
26
|
+
obj.main_image = image
|
27
|
+
yield obj
|
28
|
+
for obj in rt.models.publisher.make_demo_pages(home_children):
|
29
|
+
yield iterate(obj)
|
30
|
+
|
lino/modlib/publisher/models.py
CHANGED
@@ -9,10 +9,13 @@ from django.conf import settings
|
|
9
9
|
from django.utils import translation
|
10
10
|
from django.utils.translation import pgettext_lazy
|
11
11
|
|
12
|
-
from lorem import get_paragraph
|
13
12
|
from django.utils import translation
|
14
13
|
from django.conf import settings
|
15
14
|
|
15
|
+
try:
|
16
|
+
from lorem import get_paragraph
|
17
|
+
except ImportError:
|
18
|
+
lorem = None
|
16
19
|
|
17
20
|
# from django.utils.translation import get_language
|
18
21
|
from django.utils.html import mark_safe
|
@@ -160,16 +163,6 @@ class Page(
|
|
160
163
|
|
161
164
|
# if not self.is_public():
|
162
165
|
# return
|
163
|
-
if hlevel == 1 and self.main_image:
|
164
|
-
yield f"""
|
165
|
-
<div class="row">
|
166
|
-
<div class="center-block">
|
167
|
-
<a href="#" class="thumbnail">
|
168
|
-
<img src="{self.main_image.get_media_file().get_image_url()}">
|
169
|
-
</a>
|
170
|
-
</div>
|
171
|
-
</div>
|
172
|
-
"""
|
173
166
|
|
174
167
|
if display_mode in ("detail",):
|
175
168
|
info = self.get_node_info(ar)
|
@@ -182,9 +175,20 @@ class Page(
|
|
182
175
|
|
183
176
|
# if display_mode in ("detail", "story"):
|
184
177
|
if display_mode == "detail":
|
185
|
-
if hlevel == 1 and not dd.plugins.memo.use_markup:
|
178
|
+
if hlevel == 1 and not dd.plugins.memo.use_markup and self.ref != 'index':
|
186
179
|
yield self.toc_html(ar)
|
187
180
|
|
181
|
+
if hlevel == 1 and self.main_image:
|
182
|
+
yield f"""
|
183
|
+
<div class="row">
|
184
|
+
<div class="center-block">
|
185
|
+
<a href="#" class="thumbnail">
|
186
|
+
<img src="{self.main_image.get_media_file().get_image_url()}">
|
187
|
+
</a>
|
188
|
+
</div>
|
189
|
+
</div>
|
190
|
+
"""
|
191
|
+
|
188
192
|
# yield self.body_full_preview
|
189
193
|
yield self.get_body_parsed(ar, short=False)
|
190
194
|
|
lino/utils/__init__.py
CHANGED
@@ -63,7 +63,6 @@ import traceback
|
|
63
63
|
from dateutil.relativedelta import relativedelta
|
64
64
|
import re
|
65
65
|
from decimal import Decimal
|
66
|
-
from collections import OrderedDict
|
67
66
|
from urllib.parse import urlencode
|
68
67
|
|
69
68
|
# import locale
|
@@ -76,6 +75,7 @@ from etgen.utils import join_elems
|
|
76
75
|
|
77
76
|
from lino.utils.cycler import Cycler
|
78
77
|
from lino.utils.code import codefiles, codetime
|
78
|
+
from .sums import SumCollector
|
79
79
|
|
80
80
|
from rstgen.utils import confirm, i2d, i2t
|
81
81
|
|
@@ -609,61 +609,6 @@ def puts(s):
|
|
609
609
|
print(s)
|
610
610
|
|
611
611
|
|
612
|
-
class SumCollector(object):
|
613
|
-
"""A dictionary of sums to be collected using an arbitrary key.
|
614
|
-
|
615
|
-
This is also included in the default context used by the Jinja
|
616
|
-
renderer (:mod:`lino.modlib.jinja`) when rendering templates,
|
617
|
-
which makes it a more complete solution for a problem asked also
|
618
|
-
elsewhere, e.g. on `Stackoverflow
|
619
|
-
<https://stackoverflow.com/questions/7537439/how-to-increment-a-variable-on-a-for-loop-in-jinja-template>`__.
|
620
|
-
|
621
|
-
See examples in :doc:`/topics/utils`.
|
622
|
-
|
623
|
-
"""
|
624
|
-
|
625
|
-
def __init__(self):
|
626
|
-
self._sums = OrderedDict()
|
627
|
-
|
628
|
-
def collect(self, k, value):
|
629
|
-
"""Add the given value to the sum at the given key k."""
|
630
|
-
if value is None:
|
631
|
-
return
|
632
|
-
if k in self._sums:
|
633
|
-
# print("20230614 a", k, "=", self._sums[k], "+", value)
|
634
|
-
self._sums[k] += value
|
635
|
-
else:
|
636
|
-
# print("20230614 b", k, "=", value)
|
637
|
-
self._sums[k] = value
|
638
|
-
|
639
|
-
def __getattr__(self, k):
|
640
|
-
return self._sums.get(k)
|
641
|
-
|
642
|
-
def __getitem__(self, k):
|
643
|
-
return self._sums.get(k)
|
644
|
-
|
645
|
-
def total(self):
|
646
|
-
return sum(self._sums.values())
|
647
|
-
|
648
|
-
def items(self, *args, **kwargs):
|
649
|
-
return self._sums.items(*args, **kwargs)
|
650
|
-
|
651
|
-
def keys(self, *args, **kwargs):
|
652
|
-
return self._sums.keys(*args, **kwargs)
|
653
|
-
|
654
|
-
def values(self, *args, **kwargs):
|
655
|
-
return self._sums.values(*args, **kwargs)
|
656
|
-
|
657
|
-
def __len__(self):
|
658
|
-
return self._sums.__len__()
|
659
|
-
|
660
|
-
def __str__(self):
|
661
|
-
return str(self._sums)
|
662
|
-
|
663
|
-
def __repr__(self):
|
664
|
-
return repr(self._sums)
|
665
|
-
|
666
|
-
|
667
612
|
class SimpleSingleton(object):
|
668
613
|
_instance = None
|
669
614
|
|
lino/utils/sums.py
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
# Copyright 2012-2025 Rumma & Ko Ltd
|
3
|
+
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
|
+
# Documentation: https://dev.lino-framework.org/plugins/accounting.html
|
5
|
+
|
6
|
+
from collections import OrderedDict
|
7
|
+
from decimal import Decimal, ROUND_HALF_UP
|
8
|
+
|
9
|
+
ZERO = Decimal(0)
|
10
|
+
CENT = Decimal('.01')
|
11
|
+
HUNDRED = Decimal('100.00')
|
12
|
+
ONE = Decimal('1.00')
|
13
|
+
MAX_AMOUNT = Decimal("9999999.00")
|
14
|
+
|
15
|
+
|
16
|
+
def myround(d):
|
17
|
+
return d.quantize(CENT, rounding=ROUND_HALF_UP)
|
18
|
+
|
19
|
+
|
20
|
+
class SumCollector:
|
21
|
+
"""A dictionary of sums to be collected using an arbitrary key.
|
22
|
+
|
23
|
+
This is also included in the default context used by the Jinja
|
24
|
+
renderer (:mod:`lino.modlib.jinja`) when rendering templates,
|
25
|
+
which makes it a more complete solution for a problem asked also
|
26
|
+
elsewhere, e.g. on `Stackoverflow
|
27
|
+
<https://stackoverflow.com/questions/7537439/how-to-increment-a-variable-on-a-for-loop-in-jinja-template>`__.
|
28
|
+
|
29
|
+
See examples in :doc:`/topics/utils`.
|
30
|
+
|
31
|
+
"""
|
32
|
+
|
33
|
+
def __init__(self):
|
34
|
+
self._sums = OrderedDict()
|
35
|
+
|
36
|
+
def collect(self, k, value):
|
37
|
+
"""Add the given value to the sum at the given key k."""
|
38
|
+
if value is None:
|
39
|
+
return
|
40
|
+
if k in self._sums:
|
41
|
+
# print("20230614 a", k, "=", self._sums[k], "+", value)
|
42
|
+
self._sums[k] += value
|
43
|
+
else:
|
44
|
+
# print("20230614 b", k, "=", value)
|
45
|
+
self._sums[k] = value
|
46
|
+
|
47
|
+
def myround(self):
|
48
|
+
self._sums = {k: myround(v) for k, v in self._sums.items()}
|
49
|
+
|
50
|
+
def __getattr__(self, k):
|
51
|
+
return self._sums.get(k)
|
52
|
+
|
53
|
+
def __getitem__(self, k):
|
54
|
+
return self._sums.get(k)
|
55
|
+
|
56
|
+
def total(self):
|
57
|
+
return sum(self._sums.values())
|
58
|
+
|
59
|
+
def items(self, *args, **kwargs):
|
60
|
+
return self._sums.items(*args, **kwargs)
|
61
|
+
|
62
|
+
def keys(self, *args, **kwargs):
|
63
|
+
return self._sums.keys(*args, **kwargs)
|
64
|
+
|
65
|
+
def values(self, *args, **kwargs):
|
66
|
+
return self._sums.values(*args, **kwargs)
|
67
|
+
|
68
|
+
def __len__(self):
|
69
|
+
return self._sums.__len__()
|
70
|
+
|
71
|
+
def __str__(self):
|
72
|
+
return str(self._sums)
|
73
|
+
|
74
|
+
def __repr__(self):
|
75
|
+
return repr(self._sums)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: lino
|
3
|
-
Version: 25.4.
|
3
|
+
Version: 25.4.5
|
4
4
|
Summary: A framework for writing desktop-like web applications using Django and ExtJS or React
|
5
5
|
Project-URL: Homepage, https://www.lino-framework.org
|
6
6
|
Project-URL: Repository, https://gitlab.com/lino-framework/lino
|
@@ -1,10 +1,10 @@
|
|
1
1
|
lino/.cvsignore,sha256=1vrrWoP-WD8hPfCszHHIiJEi8KUMRCt5WvoKB9TSB1k,28
|
2
2
|
lino/SciTEDirectory.properties,sha256=rCYi_e-6h8Yx5DwXhAa6MBPlVINcl6Vv9BQDYZV2_go,28
|
3
|
-
lino/__init__.py,sha256=
|
3
|
+
lino/__init__.py,sha256=BwMhah1-EWVulbl6pSZkJqaPAx15Bc3Lg58OFimYFqI,6176
|
4
4
|
lino/ad.py,sha256=AQ-vJ4scac1mx3xegXezxnxyOQpV-a0q3VFMJSDbj2s,142
|
5
5
|
lino/apps.py,sha256=ECq-dPARDkuhngwNrcipse3b4Irj70HxJs44uWEZFc4,27
|
6
6
|
lino/hello.py,sha256=7-PJg7PnEiznyETqGjOwXcKh8rda0qLetpbS2gvRYy0,532
|
7
|
-
lino/help_texts.py,sha256=
|
7
|
+
lino/help_texts.py,sha256=z4EGZdwOchg1_ksrjA3oWaQUlFRCxF14JpK4e8WHihY,91224
|
8
8
|
lino/api/__init__.py,sha256=WmzHU-rHdZ68se_nI0SmepQTGE8-cd9tPpovHRH9aag,512
|
9
9
|
lino/api/ad.py,sha256=F6SrcKPRRalHKOZ7QLwsRWGq9hhykQIeo0b85cEk9NQ,314
|
10
10
|
lino/api/dd.py,sha256=-mxiSJS27LGCWyOgboA8qDudTkE9vg9vmUGOT08Hq6A,7410
|
@@ -42,12 +42,12 @@ lino/core/ddh.py,sha256=dYScxWKTOCDEgow7wJNJe812ESasmmITPK2ovraBQno,3172
|
|
42
42
|
lino/core/diff.py,sha256=XQ-oQQDS_v3kXd4eRP9Hwr5UCgp-TPZIPVav9ZblUno,5882
|
43
43
|
lino/core/elems.py,sha256=3PZ-0RDr6c8QoZa9sWKV36w-wn1Oj2xFpjW8eHrEpzs,108811
|
44
44
|
lino/core/exceptions.py,sha256=QDxDo5cllSyXQ8VWet9hGXzNadxCOmwMVrFXc6V-vpE,665
|
45
|
-
lino/core/fields.py,sha256=
|
45
|
+
lino/core/fields.py,sha256=zPP90oYxodCyF4DzE62008fUzH75C5RimOtoaWbfRz4,58231
|
46
46
|
lino/core/frames.py,sha256=ISxgq9zyZfqW3tDZMWdKi9Ij455lT_81qBH0xex0bfE,1161
|
47
47
|
lino/core/gfks.py,sha256=6VXn2FSIXOrwVq0stfbPevT37EWg1tg4Fn-HMNVnbmk,1970
|
48
48
|
lino/core/help.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
49
49
|
lino/core/inject.py,sha256=Qd_PGEn0yMXNYVPI0wCv1vvo2CNdlPkyoBmKZELOtGM,13422
|
50
|
-
lino/core/kernel.py,sha256=
|
50
|
+
lino/core/kernel.py,sha256=kKgKmgUZqh7rFqpKjuM_T6pUvaw7K_vl3PEfRqvrg8Q,47794
|
51
51
|
lino/core/keyboard.py,sha256=W3jA6qtB5HMppoNnd_6PgIM7ZlyHilJEhBvdeZTY7Xk,1283
|
52
52
|
lino/core/layouts.py,sha256=Wojx5UUyhy7PsZE8FWmiXcmZDj4wz2y_1_wlz1G560Q,28663
|
53
53
|
lino/core/menus.py,sha256=W0Co9K-ayvfX5Zt5rgSxJrFRejtiYrwIR5EecdYXPNc,10857
|
@@ -56,16 +56,16 @@ lino/core/model.py,sha256=YENZ-v1sggtdTitgmC8jBmuihN1EsKXQMlbPAuTSat8,36870
|
|
56
56
|
lino/core/permissions.py,sha256=Fnemz3NwWz21X0YATI9Q7ba2FcAdg-EMLHjIcbt_AVU,6840
|
57
57
|
lino/core/plugin.py,sha256=8FdxFF5tqHK-N8aXANzpWXY97hj6Lty4ulM6PWcq5A8,6833
|
58
58
|
lino/core/renderer.py,sha256=C00J0L41hLv9b2sAzqSSrT0Lz5Fc78JnwHiq9LqF81c,47310
|
59
|
-
lino/core/requests.py,sha256=
|
59
|
+
lino/core/requests.py,sha256=aIT8DsWVWwYQWHf7xX7SbbUf0s_8dWfayR3104VDrnQ,95833
|
60
60
|
lino/core/roles.py,sha256=PXwk436xUupxdbJcygRSYFu7ixfKjAJPQRUQ8sy0lB0,4425
|
61
61
|
lino/core/signals.py,sha256=0JT89mkjSbRm57QZcSI9DoThoKUGkyi-egNhuLUKEds,948
|
62
|
-
lino/core/site.py,sha256=
|
62
|
+
lino/core/site.py,sha256=WqL_QrimT85POO7wKp3R4s8O4P_tvOOxg6WDO968vOQ,82796
|
63
63
|
lino/core/store.py,sha256=6pd4J5Y-U7Muz4mKFSL6K9KEZpJUbpM-I7RQTWyCo-8,51483
|
64
64
|
lino/core/tables.py,sha256=Yoj-H2ASW9xIger8kuW8xst5A_tEmtWpV17L11Ebca0,24348
|
65
65
|
lino/core/urls.py,sha256=06QlmN1vpxjmb5snO3SPpP6lX1pMdE60bTiBiC77_vQ,2677
|
66
66
|
lino/core/user_types.py,sha256=0iSYmzr2M9v2Mn2y6hzAZeqareUT-gD7l3MfIPyG9ZI,867
|
67
67
|
lino/core/userprefs.py,sha256=cmufIS9xJErKDrw05uoWtQTUR6WRWIGkU1KdAqzNr5M,2850
|
68
|
-
lino/core/utils.py,sha256=
|
68
|
+
lino/core/utils.py,sha256=6yFnP9BFOW5O4oABdv0ASAeJf6oYQ7BZioEqtBBTVzk,36618
|
69
69
|
lino/core/views.py,sha256=qLjEN6GSXScbmAnKN7yDHySmsjL0h4sMKRIQCpOEdPU,7026
|
70
70
|
lino/core/widgets.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
71
71
|
lino/core/workflows.py,sha256=9O5INnx3nPW73UmeEPWgN146clQSWwna3Jq_w1MThcg,10567
|
@@ -123,7 +123,7 @@ lino/mixins/periods.py,sha256=iFqUCUZlgUW2GmEHRl9suwJedztrXLluQhgFpu7Uj54,11479
|
|
123
123
|
lino/mixins/polymorphic.py,sha256=MLbfOeIYRoDZO4048X2oWhG5cxds2pLkwciXcw1xjVQ,9393
|
124
124
|
lino/mixins/printable.py,sha256=4U8M1lrTjUeuaPwrcWoanCBo53iAxiNpSTsVctI-gI0,199
|
125
125
|
lino/mixins/ref.py,sha256=ZnyTcpHgcbYwDwgaBwLc5cGLQqz8MmjAypSEgPB7Ql4,5272
|
126
|
-
lino/mixins/registrable.py,sha256=
|
126
|
+
lino/mixins/registrable.py,sha256=EqszzywB9LN37zl7NRBHZxsHzFRoBQb-f9HBkSHo0vw,7206
|
127
127
|
lino/mixins/sequenced.py,sha256=6FiHJX2ZIraqUofdnb082b978PISNbpd2Vr87YA_1pg,16460
|
128
128
|
lino/modlib/__init__.py,sha256=cO31gNu2oRkp7o2v3D9gK2H7j4jF9rbVyPxPZhZQwrQ,940
|
129
129
|
lino/modlib/about/__init__.py,sha256=jhqGQIXU1o7KkmmQjfwPKJc3buibB09Fy55carAmi7U,342
|
@@ -3517,7 +3517,7 @@ lino/modlib/ipdict/models.py,sha256=9-pjj_xXdndhQaQI8sgXcmODxurST_aFcShGwomiYKk,
|
|
3517
3517
|
lino/modlib/jinja/__init__.py,sha256=XSa-e1qZGabl8EmRDKPRtmzgBRole5ZbxAUBR_m-ds0,3418
|
3518
3518
|
lino/modlib/jinja/choicelists.py,sha256=QHjWQWLnJCKSGnLIKeGqnCw41JYvcbTkCeXjBpWh23w,1466
|
3519
3519
|
lino/modlib/jinja/loader.py,sha256=MX027X_UuQPqq0wOUr06QnOkdTzGpksNv0Om1CGp61I,1765
|
3520
|
-
lino/modlib/jinja/mixins.py,sha256=
|
3520
|
+
lino/modlib/jinja/mixins.py,sha256=YqvNt1JB7as6IohBoyP8DqHldxmg9yOfrN27V5cn7Ho,2913
|
3521
3521
|
lino/modlib/jinja/models.py,sha256=vXNFS78qP-qIzeSmnXJNOpvW_IfH1h6hhPgYjfkvvD0,207
|
3522
3522
|
lino/modlib/jinja/renderer.py,sha256=PtjhJdidlOOGzRdyUQlaEIj2FhFFuthFB80-bkSfsoM,6156
|
3523
3523
|
lino/modlib/jinja/config/jinja/status.jinja.rst,sha256=XEsfXd82B0fLsBfds5-pXdeDWVr4ccTv7WyGa9ayigk,312
|
@@ -3534,7 +3534,7 @@ lino/modlib/languages/fixtures/iso-639-3_20100707.tab,sha256=u8PwI2s8shy0_Val5-s
|
|
3534
3534
|
lino/modlib/linod/__init__.py,sha256=efmj_Kz3OO2zF1lvs7P459iufYGimH1-6Ge6Cbq85tQ,2665
|
3535
3535
|
lino/modlib/linod/choicelists.py,sha256=Cu82s1QpcGFmKUXJsg-7TSqpaESBCZKOEfxzFlJP06I,2626
|
3536
3536
|
lino/modlib/linod/consumers.py,sha256=XBjA1fflJ-e9yWRMKXyQAhrOklYzs5JRhEeGMOKWFqM,6730
|
3537
|
-
lino/modlib/linod/mixins.py,sha256=
|
3537
|
+
lino/modlib/linod/mixins.py,sha256=Dff7rX5Ih0uJul0jID6tdY5CIZa6z6iq9feXIjNohkQ,11691
|
3538
3538
|
lino/modlib/linod/models.py,sha256=yqGytDq7KxkHBCZpwF-7GQdR3nGh6-rBB-gLkvqoouQ,2361
|
3539
3539
|
lino/modlib/linod/routing.py,sha256=3pYJT6FbaVMj6rKkDVv3E5VTFFc9nglIDeo6dgAKu8Q,2399
|
3540
3540
|
lino/modlib/linod/utils.py,sha256=dE973Xib6Be1DvNsZ0M5wzY_jpkk35R21WKs-jQPorM,339
|
@@ -3542,7 +3542,7 @@ lino/modlib/linod/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
3542
3542
|
lino/modlib/linod/fixtures/linod.py,sha256=qCFU2IktRVEdt1lChwu6kZLLnd4Ppfq_x9_2qGYelTY,1173
|
3543
3543
|
lino/modlib/linod/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3544
3544
|
lino/modlib/linod/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3545
|
-
lino/modlib/linod/management/commands/linod.py,sha256=
|
3545
|
+
lino/modlib/linod/management/commands/linod.py,sha256=WjtRgcNxSHEZFClvQTQD8DAlVD_P5qK40ZG8xmsuQgM,3115
|
3546
3546
|
lino/modlib/memo/__init__.py,sha256=GdzNURo3v_o5PxTBZ_KNkzrjlcDzn4AO95pYBbHmk8Q,5389
|
3547
3547
|
lino/modlib/memo/mixins.py,sha256=wk1bwb28GTBwXI2QJSo-6kJLfpjFwXTf5S8McjmZ0Gw,11251
|
3548
3548
|
lino/modlib/memo/models.py,sha256=zUEvWu0dK5QhkU3DeMqNqsrzSUzOl6DLZaJBNytfgrs,4388
|
@@ -3590,7 +3590,7 @@ lino/modlib/printing/config/report/Default.wk.html,sha256=4Ssx2LWm1gVpXf0Q4XoSY1
|
|
3590
3590
|
lino/modlib/publisher/__init__.py,sha256=bGQduKmgzr_lU2N6H4q4I5ZmW-3iwdPuT2D8dpiVOiI,2644
|
3591
3591
|
lino/modlib/publisher/choicelists.py,sha256=gVzjyp1sJ-XewAW-I_bCrKdTLgygLzh1ZwFI1rKyPdo,9070
|
3592
3592
|
lino/modlib/publisher/mixins.py,sha256=yRxAtFSNe9aVvdY-th_a5wmQ76jBfKYWzeNUn-efJMA,6651
|
3593
|
-
lino/modlib/publisher/models.py,sha256=
|
3593
|
+
lino/modlib/publisher/models.py,sha256=Yn6MRp2_iHIXw-kwlfaQP4mfSkVPJdjEBJ8pqgltcPQ,17260
|
3594
3594
|
lino/modlib/publisher/renderer.py,sha256=9RoyVMQcbwh_GcbDJO8BWhCKe1kpbDc9M45hrMqzpNs,1922
|
3595
3595
|
lino/modlib/publisher/ui.py,sha256=qWp3JWhO6zN_HSZvSlolmNTgiZgoJeY2_TIDh9nYf3Q,4491
|
3596
3596
|
lino/modlib/publisher/views.py,sha256=_0ktDagke4TOWVekJOnaRJBrbKqn27Yfz3SC2UnHKTM,2423
|
@@ -3598,11 +3598,11 @@ lino/modlib/publisher/config/publisher/base.html,sha256=nrWuN4lhP1O4ORdYTaY3fS2p
|
|
3598
3598
|
lino/modlib/publisher/config/publisher/default_list.pub.html,sha256=3ePc4U3xZxE-pqtzlnB9CRQWu8OQrtfXKEjyuc8BBUQ,578
|
3599
3599
|
lino/modlib/publisher/config/publisher/item.pub.html,sha256=973RYgCAYG1SYIB4bwfVZFVTUo0WD2I98PsoPgjQ8XA,154
|
3600
3600
|
lino/modlib/publisher/config/publisher/login.html,sha256=_j_MmwVv_UohMnEDADo99XQmUqGvOWTlCDPW1oaSWpo,495
|
3601
|
-
lino/modlib/publisher/config/publisher/page.pub.html,sha256=
|
3601
|
+
lino/modlib/publisher/config/publisher/page.pub.html,sha256=kjUTHInDLu25QiOyZDpxumMBt2zjMLbDrMEiJhm6y5g,2568
|
3602
3602
|
lino/modlib/publisher/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3603
3603
|
lino/modlib/publisher/fixtures/demo2.py,sha256=KrF672tNLlhMX6EkxKDfcvvE9pGH4k9NgF7Rk5DkiLg,366
|
3604
3604
|
lino/modlib/publisher/fixtures/std.py,sha256=7xpMOr4kd-4SX8uhwxagktUlcXAr6fdZfD-H519CR6g,987
|
3605
|
-
lino/modlib/publisher/fixtures/synodalworld.py,sha256=
|
3605
|
+
lino/modlib/publisher/fixtures/synodalworld.py,sha256=7OPQXVq2Ou8fcRlNli0UFXoGhGPtC6AVXnGoCqn5oKc,767
|
3606
3606
|
lino/modlib/restful/__init__.py,sha256=9CqWTQkJ2KpLW5MI1bKqKZU_7nXxodxl7HSgc8Agwmw,1506
|
3607
3607
|
lino/modlib/restful/fields.py,sha256=8dik0q2LaCtJhQX1lu-fe-y_38xdhAWy1ZX3EKmJWfs,567
|
3608
3608
|
lino/modlib/restful/serializers.py,sha256=AVyA19UkRUJ9AjlUN0fJyrj1LgfOyp-a2ANcVkecWtA,1143
|
@@ -4579,7 +4579,7 @@ lino/templates_old/404.html,sha256=9O5EJgULwLws0X1LjNig3xT4l9Hw04MBIGswD-EAlnw,2
|
|
4579
4579
|
lino/templates_old/500.html,sha256=inOR744w4FGJM_fCSQcnlk-OIYQpaBTxUQWgXQozon4,496
|
4580
4580
|
lino/templates_old/base.html,sha256=qYqj5-u1UPtpatrFkqBr3MnwS0oFUXCyQRcuNZczDfk,1641
|
4581
4581
|
lino/templates_old/base_site.html,sha256=NcLEk0kBT1b-SrhoGpDPUej7NExqJ9-dP1kbrvwBzrs,255
|
4582
|
-
lino/utils/__init__.py,sha256=
|
4582
|
+
lino/utils/__init__.py,sha256=6zmXTodRdV_hmdCcWsn_vBJUFlMZupc8O55vAOvWS9w,16838
|
4583
4583
|
lino/utils/addressable.py,sha256=o7bmLbyvrmOoAT478s7XqjWKvnZ7zSXj4k7Xf0ccqf8,2213
|
4584
4584
|
lino/utils/ajax.py,sha256=npCS0WumhTQlBzXxQPKnp2sYCRcPsYcbFqzE2ykVc4Q,3254
|
4585
4585
|
lino/utils/choosers.py,sha256=9jjeLz-QcWVBfR8_GdY4PNYoqIYM63OI3OvOL2l1ZaU,17604
|
@@ -4625,6 +4625,7 @@ lino/utils/soup.py,sha256=tQNk9MweAWH9s14rCPQI0XNc4vuWrEc2leBGqnGrsCg,10937
|
|
4625
4625
|
lino/utils/sql.py,sha256=kwCgv5E3n7uLjpXOEiaF2W2p8LeGXcP39xgtnqvzTP8,6795
|
4626
4626
|
lino/utils/sqllog.py,sha256=kUCnBfFjExhItJ1w76WT9VWPaWWq8NQM-kSIMIIZnRU,3282
|
4627
4627
|
lino/utils/ssin.py,sha256=Wo-9M0pG0uEYEGvmz8N--iRIqJe3ETtgLOXoung7qlE,4232
|
4628
|
+
lino/utils/sums.py,sha256=SATwDna9_B8_slLOBp47xO5fWtdgObhy66ux1eZf1u4,2136
|
4628
4629
|
lino/utils/test.py,sha256=_aKfp3PdOq2KzR2uTev7joix9bs_cN22QprozmUzvUI,7680
|
4629
4630
|
lino/utils/textfields.py,sha256=suTUK_zwTcxT1eHWAlif_AoRXxG_0AW6JhdbOv1zDSQ,2239
|
4630
4631
|
lino/utils/ucsv.py,sha256=KjhGh7K_yxQOM0gHWjn4BjPdi_1aLPHkem5J8nNCqD4,2235
|
@@ -4634,8 +4635,8 @@ lino/utils/xml.py,sha256=EGDnO1UaREst9fS7KTESdbHnrrVCwKbRQdvut6B6GmQ,1612
|
|
4634
4635
|
lino/utils/mldbc/__init__.py,sha256=QqWRlzeXaOmFfbCk-vTY3SZMn1-FCf67XnpZdd_Nim0,1134
|
4635
4636
|
lino/utils/mldbc/fields.py,sha256=tAX8G5UKigr9c6g0F3ARIjZZtg406mdaZ--PWSbiH9E,2873
|
4636
4637
|
lino/utils/mldbc/mixins.py,sha256=CkYe5jDa7xp9fJq_V8zcZf8ocxgIjUgHc9KZccvA_Yw,1945
|
4637
|
-
lino-25.4.
|
4638
|
-
lino-25.4.
|
4639
|
-
lino-25.4.
|
4640
|
-
lino-25.4.
|
4641
|
-
lino-25.4.
|
4638
|
+
lino-25.4.5.dist-info/METADATA,sha256=iRK3Rzw51gGXTd8xkApmMmpq6BLWOZZC3WV-3NFQLTw,42534
|
4639
|
+
lino-25.4.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
4640
|
+
lino-25.4.5.dist-info/licenses/AUTHORS.rst,sha256=8VEm_G4HOmYEa4oi1nVoKKsdo4JanekEJCefWd2E8vk,981
|
4641
|
+
lino-25.4.5.dist-info/licenses/COPYING,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
4642
|
+
lino-25.4.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|