lino 25.1.3__py3-none-any.whl → 25.1.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/actions.py +1 -0
- lino/core/fields.py +1 -0
- lino/core/layouts.py +3 -1
- lino/core/requests.py +6 -6
- lino/core/store.py +5 -4
- lino/locale/fr/LC_MESSAGES/django.mo +0 -0
- lino/locale/fr/LC_MESSAGES/django.po +4 -5
- lino/management/commands/demotest.py +5 -5
- lino/management/commands/makescreenshots.py +3 -2
- lino/modlib/comments/fixtures/demo2.py +30 -9
- lino/modlib/uploads/__init__.py +5 -7
- lino/modlib/uploads/fixtures/demo.py +53 -0
- lino/modlib/uploads/ui.py +1 -1
- lino/modlib/users/__init__.py +1 -0
- lino/modlib/users/fixtures/demo2.py +4 -3
- lino/modlib/users/ui.py +3 -7
- lino/utils/dbfreader.py +51 -50
- {lino-25.1.3.dist-info → lino-25.1.5.dist-info}/METADATA +1 -1
- {lino-25.1.3.dist-info → lino-25.1.5.dist-info}/RECORD +23 -22
- {lino-25.1.3.dist-info → lino-25.1.5.dist-info}/WHEEL +0 -0
- {lino-25.1.3.dist-info → lino-25.1.5.dist-info}/licenses/AUTHORS.rst +0 -0
- {lino-25.1.3.dist-info → lino-25.1.5.dist-info}/licenses/COPYING +0 -0
lino/__init__.py
CHANGED
lino/core/actions.py
CHANGED
@@ -1091,6 +1091,7 @@ class CreateRow(Action):
|
|
1091
1091
|
return
|
1092
1092
|
|
1093
1093
|
ar.goto_instance(elem)
|
1094
|
+
# print(f"20250121d eval_js response for {ar} is {ar.response['eval_js']}")
|
1094
1095
|
|
1095
1096
|
# No need to ask refresh_all since closing the window will
|
1096
1097
|
# automatically refresh the underlying window.
|
lino/core/fields.py
CHANGED
@@ -1336,6 +1336,7 @@ class TableRow(object):
|
|
1336
1336
|
if dt is not None:
|
1337
1337
|
a = dt.get_request_detail_action(ar)
|
1338
1338
|
# a = dt.detail_action
|
1339
|
+
# print(f"20250121 {ar} {ar.actor} {dt} {a}")
|
1339
1340
|
if a is None or ar is None:
|
1340
1341
|
return a
|
1341
1342
|
if a.get_view_permission(ar.get_user().user_type):
|
lino/core/layouts.py
CHANGED
@@ -805,7 +805,9 @@ class ParamsLayout(BaseLayout):
|
|
805
805
|
def get_data_elem(self, name):
|
806
806
|
de = self._datasource.get_param_elem(name)
|
807
807
|
if de is None:
|
808
|
-
|
808
|
+
# no longer return a data element when no param element exists:
|
809
|
+
raise Exception(f"No parameter '{name}' in {self._datasource}")
|
810
|
+
# de = self._datasource.get_data_elem(name)
|
809
811
|
de.editable = True # 20200425
|
810
812
|
# if "__" in name:
|
811
813
|
# print("20200425 ParamsLayout.get_data_elem()", name, de)
|
lino/core/requests.py
CHANGED
@@ -495,7 +495,7 @@ class BaseRequest:
|
|
495
495
|
if self.actor is not None:
|
496
496
|
if master is None:
|
497
497
|
master = self.actor.master
|
498
|
-
if master_type
|
498
|
+
if master_type and ContentType is not None:
|
499
499
|
try:
|
500
500
|
master = ContentType.objects.get(pk=master_type).model_class()
|
501
501
|
except ContentType.DoesNotExist:
|
@@ -2123,11 +2123,11 @@ class ActionRequest(BaseRequest):
|
|
2123
2123
|
if self._status is not None and not kw:
|
2124
2124
|
return self._status
|
2125
2125
|
if self.actor.parameters:
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
)
|
2126
|
+
pv = self.actor.params_layout.params_store.pv2dict(self, self.param_values)
|
2127
|
+
# print(f"20250121c {self}\n{self.actor.params_layout.params_store.__class__}\n{self.actor.params_layout.params_store.param_fields}")
|
2128
|
+
# print(f"20250121c {self} {self.param_values.keys()}\n{self.actor.params_layout}\n{pv.keys()}")
|
2129
|
+
# print(f"20250121c {self}|{self.actor.params_layout.params_store}\n{}")
|
2130
|
+
kw.update(param_values=pv)
|
2131
2131
|
|
2132
2132
|
kw = self.bound_action.action.get_status(self, **kw)
|
2133
2133
|
bp = kw.setdefault("base_params", {})
|
lino/core/store.py
CHANGED
@@ -1078,11 +1078,12 @@ class BaseStore(object):
|
|
1078
1078
|
|
1079
1079
|
|
1080
1080
|
class ParameterStore(BaseStore):
|
1081
|
-
# instantiated in `lino.core.layouts`
|
1081
|
+
# Lazily instantiated in `lino.core.layouts`
|
1082
1082
|
def __init__(self, params_layout_handle, url_param):
|
1083
|
-
|
1083
|
+
param_fields = []
|
1084
1084
|
|
1085
1085
|
holder = params_layout_handle.layout.get_chooser_holder()
|
1086
|
+
# print(f"20250121e {holder}")
|
1086
1087
|
# debug = False
|
1087
1088
|
for pf in params_layout_handle._data_elems:
|
1088
1089
|
sf = create_atomizer(holder, pf, pf.name)
|
@@ -1090,12 +1091,12 @@ class ParameterStore(BaseStore):
|
|
1090
1091
|
# if "__" in pf.name:
|
1091
1092
|
# print("20200423 ParameterStore", pf.name, sf)
|
1092
1093
|
# debug = True
|
1093
|
-
|
1094
|
+
param_fields.append(sf)
|
1094
1095
|
|
1095
1096
|
# if debug:
|
1096
1097
|
# print("20200423 ParameterStore2", self.param_fields)
|
1097
1098
|
|
1098
|
-
self.param_fields = tuple(
|
1099
|
+
self.param_fields = tuple(param_fields)
|
1099
1100
|
self.url_param = url_param
|
1100
1101
|
self.params_layout_handle = params_layout_handle
|
1101
1102
|
|
Binary file
|
@@ -8,7 +8,7 @@ msgstr ""
|
|
8
8
|
"Project-Id-Version: \n"
|
9
9
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
10
10
|
"POT-Creation-Date: 2024-11-16 21:41+0200\n"
|
11
|
-
"PO-Revision-Date:
|
11
|
+
"PO-Revision-Date: 2025-01-18 21:35+0200\n"
|
12
12
|
"Last-Translator: Luc Saffre <luc.saffre@gmail.com>\n"
|
13
13
|
"Language-Team: \n"
|
14
14
|
"Language: fr\n"
|
@@ -5716,7 +5716,7 @@ msgstr "Bienvenue sur <b>%s</b>."
|
|
5716
5716
|
|
5717
5717
|
#: lino/modlib/publisher/choicelists.py:234
|
5718
5718
|
msgid "Terms and conditions"
|
5719
|
-
msgstr ""
|
5719
|
+
msgstr "Conditions générales"
|
5720
5720
|
|
5721
5721
|
#: lino/modlib/publisher/choicelists.py:235
|
5722
5722
|
msgid "Privacy policy"
|
@@ -5729,12 +5729,11 @@ msgstr "Mes préférences"
|
|
5729
5729
|
|
5730
5730
|
#: lino/modlib/publisher/choicelists.py:237
|
5731
5731
|
msgid "Copyright"
|
5732
|
-
msgstr ""
|
5732
|
+
msgstr "Droits d'auteur"
|
5733
5733
|
|
5734
5734
|
#: lino/modlib/publisher/choicelists.py:238
|
5735
|
-
#, fuzzy
|
5736
5735
|
msgid "About us"
|
5737
|
-
msgstr "
|
5736
|
+
msgstr "À propos"
|
5738
5737
|
|
5739
5738
|
#: lino/modlib/publisher/models.py:55
|
5740
5739
|
#, fuzzy
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2021 Rumma & Ko Ltd
|
2
|
+
# Copyright 2021-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
|
5
5
|
from lino import logger
|
@@ -18,7 +18,7 @@ from lino.utils.test import DemoTestCase
|
|
18
18
|
|
19
19
|
|
20
20
|
class TestCase(DemoTestCase):
|
21
|
-
tested_urls = ("/", "/?su=3", "/?su=
|
21
|
+
tested_urls = ("/", "/?su=3", "/?su=123")
|
22
22
|
|
23
23
|
def test_get(self):
|
24
24
|
if False:
|
@@ -43,7 +43,7 @@ class TestCase(DemoTestCase):
|
|
43
43
|
if settings.SITE.user_model:
|
44
44
|
for user in settings.SITE.user_model.objects.all():
|
45
45
|
if user.user_type:
|
46
|
-
d = self.login(user.username,
|
46
|
+
d = self.login(user.username, dd.plugins.users.demo_password)
|
47
47
|
# self.client.force_login(user)
|
48
48
|
for url in self.tested_urls:
|
49
49
|
# logger.debug("%s gets %s", user.username, url)
|
@@ -93,7 +93,7 @@ class TestCase(DemoTestCase):
|
|
93
93
|
|
94
94
|
# Even with the right password you cannot unlock a blacklisted ip
|
95
95
|
self.assertEqual(
|
96
|
-
login(
|
96
|
+
login(dd.plugins.users.demo_password), "Too many authentication failures from 127.0.0.1"
|
97
97
|
)
|
98
98
|
|
99
99
|
# After max_blacklist_time, the IP gets removed from the blacklist, but
|
@@ -109,7 +109,7 @@ class TestCase(DemoTestCase):
|
|
109
109
|
self.assertEqual(rec.login_failures, 5)
|
110
110
|
|
111
111
|
time.sleep(1)
|
112
|
-
self.assertEqual(login(
|
112
|
+
self.assertEqual(login(dd.plugins.users.demo_password), "Now signed in as Robin Rood")
|
113
113
|
|
114
114
|
# Once you manage to authenticate, your ip address gets removed from the
|
115
115
|
# blacklist, i.e. when you log out and in for some reason, you get again
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2012-
|
2
|
+
# Copyright 2012-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
"""
|
5
5
|
Writes screenshots to <project_dir>/media/cache/screenshots
|
@@ -36,6 +36,7 @@ from django.test.testcases import StoppableWSGIServer
|
|
36
36
|
|
37
37
|
from lino.core.utils import obj2str, full_model_name, sorted_models_list
|
38
38
|
from lino.utils import screenshots
|
39
|
+
from lino.api import dd
|
39
40
|
from rstgen.utils import SubProcessParent
|
40
41
|
|
41
42
|
PHANTOMJS = "/home/luc/snapshots/phantomjs-1.9.0-linux-i686/bin/phantomjs"
|
@@ -223,7 +224,7 @@ class Command(BaseCommand):
|
|
223
224
|
ctx = dict(
|
224
225
|
url=url, target=target, username=ss.ar.get_user().username
|
225
226
|
)
|
226
|
-
ctx.update(password=
|
227
|
+
ctx.update(password=dd.plugins.users.demo_password)
|
227
228
|
ctx.update(remote_user_header=settings.SITE.remote_user_header)
|
228
229
|
f = file("tmp.js", "wt")
|
229
230
|
f.write(JS_SRC % ctx)
|
@@ -29,7 +29,8 @@ cond_comment = (
|
|
29
29
|
"<p><!--[if gte foo 123]>A conditional comment<![endif]--></p>\n<p>Hello</p>"
|
30
30
|
)
|
31
31
|
plain1 = "Some plain text."
|
32
|
-
plain2 = "Two paragraphs of plain text.\n\nThe second paragraph.
|
32
|
+
plain2 = "Two paragraphs of plain text.\n\nThe second paragraph."
|
33
|
+
# plain2 += " With an 👁 (U+1F441)." #5855 (Jane fails to store certain unicode characters)
|
33
34
|
|
34
35
|
BODIES = Cycler(
|
35
36
|
[styled, table, lorem, short_lorem, breaking, cond_comment, plain1, plain2]
|
@@ -43,11 +44,26 @@ def objects():
|
|
43
44
|
# use_linod = settings.SITE.use_linod
|
44
45
|
# settings.SITE.use_linod = False
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
# Add two empty bodies that will be filled later:
|
48
|
+
BODIES.items.insert(0, "")
|
49
|
+
BODIES.items.insert(0, "")
|
50
|
+
MENTIONED = Cycler()
|
51
|
+
for model in rt.models_by_base(Commentable):
|
52
|
+
if model.memo_command is not None:
|
53
|
+
MENTIONED.items += list(model.objects.all())
|
54
|
+
|
55
|
+
# if dd.is_installed("contacts"):
|
56
|
+
# BODIES.items.append("")
|
57
|
+
# MENTIONED = Cycler()
|
58
|
+
# MENTIONED.items += list(rt.models.contacts.Person.objects.all())
|
59
|
+
# MENTIONED.items += list(rt.models.contacts.Company.objects.all())
|
60
|
+
|
61
|
+
if dd.get_plugin_setting("uploads", "with_volumes", False):
|
62
|
+
Upload = rt.models.uploads.Upload
|
63
|
+
SCREENSHOTS = Cycler(Upload.objects.filter(volume__ref="screenshots"))
|
64
|
+
assert len(SCREENSHOTS) > 0
|
65
|
+
else:
|
66
|
+
SCREENSHOTS = None
|
51
67
|
|
52
68
|
for model in rt.models_by_base(Commentable):
|
53
69
|
OWNERS = Cycler(model.objects.order_by("-id"))
|
@@ -72,9 +88,14 @@ def objects():
|
|
72
88
|
# txt = TXT.pop() # txt = "Hackerish comment"
|
73
89
|
body = BODIES.pop()
|
74
90
|
if not body:
|
75
|
-
|
76
|
-
|
77
|
-
|
91
|
+
if SCREENSHOTS is None or i % 2:
|
92
|
+
cmd1 = MENTIONED.pop().obj2memo()
|
93
|
+
cmd2 = MENTIONED.pop().obj2memo()
|
94
|
+
body = f"This is a comment about {cmd1} and {cmd2}."
|
95
|
+
else:
|
96
|
+
upload = SCREENSHOTS.pop()
|
97
|
+
body = f"Here is a screenshot:\n\n [file {upload.pk}]"
|
98
|
+
|
78
99
|
obj = Comment(user=u, owner=owner, body=body, reply_to=reply_to)
|
79
100
|
obj.on_create(ses)
|
80
101
|
obj.after_ui_create(ses)
|
lino/modlib/uploads/__init__.py
CHANGED
@@ -29,13 +29,11 @@ class Plugin(ad.Plugin):
|
|
29
29
|
"""Whether to use PIL, the Python Imaging Library.
|
30
30
|
"""
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
#
|
36
|
-
#
|
37
|
-
# print("20240907 created", self.get_uploads_root())
|
38
|
-
# print("20240907 created", self.get_volumes_root())
|
32
|
+
with_volumes = True
|
33
|
+
"""Whether to use library files (volumes).
|
34
|
+
"""
|
35
|
+
# TODO: Also remove the Volume model and its actors when with_volumes is set
|
36
|
+
# to False.
|
39
37
|
|
40
38
|
def get_uploads_root(self):
|
41
39
|
# return join(self.site.django_settings["MEDIA_ROOT"], "uploads")
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
# Copyright 2015-2025 Rumma & Ko Ltd
|
3
|
+
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
|
+
|
5
|
+
import os
|
6
|
+
from lino.api import dd, rt
|
7
|
+
from lino.modlib.uploads.mixins import make_uploaded_file
|
8
|
+
|
9
|
+
try:
|
10
|
+
from lino_book import DEMO_DATA
|
11
|
+
except ImportError:
|
12
|
+
DEMO_DATA = None
|
13
|
+
|
14
|
+
def walk(p):
|
15
|
+
# print("20230331", p)
|
16
|
+
for c in sorted(p.iterdir()):
|
17
|
+
if c.is_dir():
|
18
|
+
for cc in walk(c):
|
19
|
+
yield cc
|
20
|
+
else:
|
21
|
+
yield c
|
22
|
+
|
23
|
+
def objects():
|
24
|
+
|
25
|
+
if DEMO_DATA is None:
|
26
|
+
# logger.info("No demo data because lino_book is not installed")
|
27
|
+
return
|
28
|
+
if not dd.plugins.uploads.with_volumes:
|
29
|
+
return
|
30
|
+
|
31
|
+
Upload = rt.models.uploads.Upload
|
32
|
+
Volume = rt.models.uploads.Volume
|
33
|
+
|
34
|
+
def load_vol(root_dir, ref, desc, **kwargs):
|
35
|
+
vol = Volume(ref=ref, description=desc, root_dir=root_dir)
|
36
|
+
yield vol
|
37
|
+
kwargs.update(volume=vol)
|
38
|
+
chop = len(str(root_dir)) + 1
|
39
|
+
for fn in walk(root_dir):
|
40
|
+
fns = str(fn)[chop:]
|
41
|
+
# print("20230325 {}".format(fn))
|
42
|
+
yield Upload(
|
43
|
+
library_file=fns,
|
44
|
+
description=fns.replace('_', ' ').replace('/', ' '),
|
45
|
+
**kwargs)
|
46
|
+
|
47
|
+
if dd.is_installed('sources'):
|
48
|
+
yield (luc := rt.models.sources.Author(first_name="Luc", last_name="Saffre"))
|
49
|
+
yield (source := rt.models.sources.Source(
|
50
|
+
author=luc, year_published="2022", title="Private collection"))
|
51
|
+
yield load_vol(DEMO_DATA / 'photos', "photos", "Photo album", source=source)
|
52
|
+
|
53
|
+
yield load_vol(DEMO_DATA / 'screenshots', "screenshots", "Screenshots")
|
lino/modlib/uploads/ui.py
CHANGED
@@ -81,7 +81,7 @@ class Uploads(dd.Table):
|
|
81
81
|
model = "uploads.Upload"
|
82
82
|
# required_roles = dd.login_required((OfficeUser, OfficeOperator))
|
83
83
|
required_roles = dd.login_required(UploadsReader)
|
84
|
-
column_names = "file type user owner
|
84
|
+
column_names = "id description file type user owner *"
|
85
85
|
order_by = ["-id"]
|
86
86
|
default_display_modes = {
|
87
87
|
70: constants.DISPLAY_MODE_LIST,
|
lino/modlib/users/__init__.py
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2012-
|
2
|
+
# Copyright 2012-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
4
|
"""
|
5
|
-
Set password
|
5
|
+
Set password to :setting:`users.demo_password` for all users.
|
6
6
|
|
7
7
|
This is an additive fixture designed to work also on existing data.
|
8
8
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
from django.conf import settings
|
12
|
+
from lino.api import dd
|
12
13
|
|
13
14
|
|
14
15
|
def objects():
|
15
16
|
for u in settings.SITE.user_model.objects.exclude(user_type=""):
|
16
|
-
u.set_password(
|
17
|
+
u.set_password(dd.plugins.users.demo_password)
|
17
18
|
yield u
|
lino/modlib/users/ui.py
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
# -*- coding: UTF-8 -*-
|
2
|
-
# Copyright 2011-
|
2
|
+
# Copyright 2011-2025 Rumma & Ko Ltd
|
3
3
|
# License: GNU Affero General Public License v3 (see file COPYING for details)
|
4
|
-
|
5
|
-
|
6
|
-
Documentation is in :doc:`/specs/users` and :doc:`/dev/users`
|
7
|
-
|
8
|
-
"""
|
4
|
+
# Documentation: :doc:`/specs/users` and :doc:`/dev/users`
|
9
5
|
|
10
6
|
from datetime import datetime
|
11
7
|
from textwrap import wrap
|
@@ -135,7 +131,7 @@ class UsersOverview(Users):
|
|
135
131
|
def row_as_paragraph(cls, ar, self):
|
136
132
|
pv = dict(username=self.username)
|
137
133
|
if settings.SITE.is_demo_site:
|
138
|
-
pv.update(password=
|
134
|
+
pv.update(password=dd.plugins.users.demo_password)
|
139
135
|
btn = rt.models.about.About.get_action_by_name("sign_in")
|
140
136
|
# print btn.get_row_permission(ar, None, None)
|
141
137
|
btn = btn.request(
|
lino/utils/dbfreader.py
CHANGED
@@ -12,16 +12,15 @@ http://www.the-oasis.net/clipper-12.html#ss12.4
|
|
12
12
|
|
13
13
|
http://www.clicketyclick.dk/databases/xbase/format/
|
14
14
|
"""
|
15
|
-
from
|
16
|
-
from builtins import
|
17
|
-
from builtins import
|
18
|
-
from builtins import object
|
15
|
+
# from builtins import hex
|
16
|
+
# from builtins import str
|
17
|
+
# from builtins import object
|
19
18
|
|
20
19
|
import datetime
|
21
20
|
from dateutil import parser as dateparser
|
22
21
|
|
23
22
|
import sys
|
24
|
-
import string
|
23
|
+
# import string
|
25
24
|
|
26
25
|
codepages = {
|
27
26
|
"\x01": "cp437",
|
@@ -32,28 +31,29 @@ codepages = {
|
|
32
31
|
|
33
32
|
|
34
33
|
def unpack_long(number):
|
35
|
-
|
36
|
-
|
34
|
+
# print(f"20250123 unpack_long {number}")
|
35
|
+
return number[0] + 256 * (
|
36
|
+
number[1] + 256 * (number[2] + 256 * number[3])
|
37
37
|
)
|
38
38
|
|
39
39
|
|
40
40
|
def unpack_long_rev(number):
|
41
|
-
return
|
42
|
-
|
41
|
+
return number[3] + 256 * (
|
42
|
+
number[2] + 256 * (number[1] + 256 * number[0])
|
43
43
|
)
|
44
44
|
|
45
45
|
|
46
46
|
def unpack_int(number):
|
47
|
-
return
|
47
|
+
return number[0] + 256 * number[1]
|
48
48
|
|
49
49
|
|
50
50
|
def unpack_int_rev(number):
|
51
|
-
return
|
51
|
+
return number[1] + 256 * number[0]
|
52
52
|
|
53
53
|
|
54
54
|
def hex_analyze(number):
|
55
55
|
for ch in number:
|
56
|
-
print("%s\t%s\t%d" % (hex(
|
56
|
+
print("%s\t%s\t%d" % (hex(ch), ch, ch))
|
57
57
|
|
58
58
|
|
59
59
|
# def sort_by_key(list,key_func):
|
@@ -76,56 +76,52 @@ class DBFFile(object):
|
|
76
76
|
HAS_MEMO_FILE = 128 # "\x80"
|
77
77
|
|
78
78
|
versionmap = {
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
79
|
+
0x03: "dBASE III",
|
80
|
+
0x83: "dBASE III+ with memo",
|
81
|
+
0x8B: "dBASE IV with memo",
|
82
|
+
0xF5: "FoxPro with memo",
|
83
83
|
}
|
84
84
|
|
85
85
|
def __init__(self, filename, codepage=None):
|
86
86
|
self.filename = filename
|
87
|
-
|
88
87
|
infile = open(self.filename, "rb")
|
89
88
|
|
90
|
-
# Read header
|
91
|
-
|
89
|
+
# Read header:
|
92
90
|
header = infile.read(32)
|
93
|
-
|
94
91
|
self.version = header[0]
|
95
|
-
year =
|
96
|
-
month =
|
97
|
-
day =
|
92
|
+
year = header[1] + 2000
|
93
|
+
month = header[2]
|
94
|
+
day = header[3]
|
98
95
|
self.lastUpdate = datetime.date(year, month, day)
|
99
|
-
|
96
|
+
# print(f"20250123 Loading {filename} (last updated {self.lastUpdate})")
|
100
97
|
self.rec_num = unpack_long(header[4:8])
|
101
|
-
|
102
98
|
self.first_rec = unpack_int(header[8:10])
|
103
|
-
|
104
99
|
self.rec_len = unpack_int(header[10:12])
|
105
|
-
|
106
100
|
self.codepage = codepage # s[header[29]]
|
107
101
|
|
108
|
-
# Read field defs
|
109
|
-
|
102
|
+
# Read field defs:
|
110
103
|
self.fields = {}
|
111
104
|
self.field_list = []
|
112
105
|
while 1:
|
113
106
|
ch = infile.read(1)
|
114
|
-
if ch ==
|
107
|
+
# if ch == 0x0D:
|
108
|
+
if ch == b'\r':
|
115
109
|
break
|
116
110
|
field = DBFField(ch + infile.read(31), self)
|
117
111
|
self.fields[field.name] = field
|
118
112
|
self.field_list.append(field)
|
113
|
+
# if len(self.field_list) > 20:
|
114
|
+
# sys.exit(1)
|
119
115
|
|
120
116
|
infile.close()
|
121
117
|
if self.has_memo():
|
122
|
-
if self.version ==
|
118
|
+
if self.version == 0x83:
|
123
119
|
self.blockfile = DBTFile(self)
|
124
120
|
else:
|
125
121
|
self.blockfile = FPTFile(self)
|
126
122
|
|
127
123
|
def has_memo(self):
|
128
|
-
if
|
124
|
+
if self.version & self.HAS_MEMO_FILE:
|
129
125
|
return True
|
130
126
|
return False
|
131
127
|
|
@@ -166,12 +162,12 @@ class DBFFile(object):
|
|
166
162
|
values = {}
|
167
163
|
ch = self.infile.read(1)
|
168
164
|
self.recno += 1
|
169
|
-
if ch ==
|
165
|
+
if ch == 0x1A or len(ch) == 0:
|
166
|
+
return None
|
167
|
+
if ch == b"*":
|
170
168
|
deleted = True
|
171
169
|
# Skip the record
|
172
170
|
# return self.get_next_record()
|
173
|
-
elif ch == "\x1A" or ch == "":
|
174
|
-
return None
|
175
171
|
else:
|
176
172
|
deleted = False
|
177
173
|
|
@@ -259,14 +255,15 @@ class DBFField(object):
|
|
259
255
|
}
|
260
256
|
|
261
257
|
def __init__(self, buf, dbf):
|
262
|
-
pos =
|
258
|
+
pos = buf.find(0)
|
263
259
|
if pos == -1 or pos > 11:
|
264
260
|
pos = 11
|
265
|
-
self.name = buf[:pos]
|
266
|
-
self.
|
261
|
+
self.name = buf[:pos].decode()
|
262
|
+
# print(f"20250123 field {self.name}")
|
263
|
+
self.field_type = chr(buf[11])
|
267
264
|
self.field_pos = unpack_long(buf[12:16])
|
268
|
-
self.field_len =
|
269
|
-
self.field_places =
|
265
|
+
self.field_len = buf[16]
|
266
|
+
self.field_places = buf[17]
|
270
267
|
self.dbf = dbf
|
271
268
|
|
272
269
|
# if self.field_type=="M" or self.field_type=="P" or \
|
@@ -289,6 +286,8 @@ class DBFField(object):
|
|
289
286
|
return self.field_len
|
290
287
|
|
291
288
|
def interpret(self, data):
|
289
|
+
# raise Exception("20250123 good")
|
290
|
+
# print(f"20250123 interpret {repr(self.field_type)}")
|
292
291
|
if self.field_type == "C":
|
293
292
|
if not self.dbf.codepage is None:
|
294
293
|
data = data.decode(self.dbf.codepage)
|
@@ -301,7 +300,8 @@ class DBFField(object):
|
|
301
300
|
return data == "Y" or data == "y" or data == "T" or data == "t"
|
302
301
|
elif self.field_type == "M":
|
303
302
|
try:
|
304
|
-
num = string.atoi(data)
|
303
|
+
# num = string.atoi(data)
|
304
|
+
num = int(data)
|
305
305
|
except ValueError:
|
306
306
|
if len(data.strip()) == 0:
|
307
307
|
# ~ return None
|
@@ -311,7 +311,8 @@ class DBFField(object):
|
|
311
311
|
|
312
312
|
elif self.field_type == "N":
|
313
313
|
try:
|
314
|
-
return string.atoi(data)
|
314
|
+
# return string.atoi(data)
|
315
|
+
return int(data)
|
315
316
|
except ValueError:
|
316
317
|
return 0
|
317
318
|
elif self.field_type == "D":
|
@@ -366,28 +367,28 @@ class DBTFile(object):
|
|
366
367
|
def __init__(self, dbf):
|
367
368
|
self.dbf = dbf
|
368
369
|
self.filename = dbf.filename[:-4] + ".DBT"
|
369
|
-
# print "DBTFile", self.filename
|
370
370
|
self.blocksize = 512
|
371
|
+
# print(f"20250123 Opening DBTFile {self.filename}")
|
371
372
|
|
372
373
|
def get_block(self, number):
|
373
374
|
infile = open(self.filename, "rb")
|
374
375
|
infile.seek(512 + self.blocksize * (number - 1))
|
375
|
-
data = ""
|
376
|
+
data = b""
|
376
377
|
while True:
|
377
378
|
buf = infile.read(self.blocksize)
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
379
|
+
if len(buf) != self.blocksize:
|
380
|
+
raise Exception(f"20250123 {number}:{len(buf)}")
|
381
|
+
data += buf
|
382
|
+
break
|
382
383
|
data += buf
|
383
|
-
pos = data.find(
|
384
|
+
pos = data.find(0x1A)
|
384
385
|
# pos = data.find("\x1A\x1A")
|
385
386
|
if pos != -1:
|
386
387
|
data = data[:pos]
|
387
388
|
break
|
388
389
|
|
389
390
|
infile.close()
|
390
|
-
if
|
391
|
+
if self.dbf.codepage is not None:
|
391
392
|
data = data.decode(self.dbf.codepage)
|
392
393
|
# clipper adds "soft CR's" to memo texts. we convert them to
|
393
394
|
# simple spaces:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: lino
|
3
|
-
Version: 25.1.
|
3
|
+
Version: 25.1.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,6 +1,6 @@
|
|
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=Mra9LM9wR3fgRgjFBaSaezhNxDMo36zcQqJfCHpCRhY,5584
|
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
|
@@ -28,7 +28,7 @@ lino/config/unused/403.html,sha256=ePwDIUXhz1iD8xXWWyt5xEvpcGIHU4LMnXma8x0ik1c,2
|
|
28
28
|
lino/config/unused/404.html,sha256=GOJrAyF6NcM69ETdSHgjff_-lvYs_-bOYhyZBem7x3I,220
|
29
29
|
lino/config/unused/500.html,sha256=aWmP37uPoMS-PJgPuBloxdx0nEreU7AvkXxsex3yVYs,544
|
30
30
|
lino/core/__init__.py,sha256=T7106QxQpa3jXAouGTIer6AXEwpkJ0NAQ9B7Q3-K6qE,686
|
31
|
-
lino/core/actions.py,sha256=
|
31
|
+
lino/core/actions.py,sha256=RiyuaK5F-VE6S7FVgSivOBx74F9H4uwGFOMEhXt66Rg,46395
|
32
32
|
lino/core/actors.py,sha256=lsp-w2kC_t_-iqeHtIYIkIPoS_jbHgZ3MZlGJWH2dyc,73663
|
33
33
|
lino/core/boundaction.py,sha256=tb0C4WwbJpAP3yKbR6OaibzcAkwVs3nfeuD0RjXTjIg,6665
|
34
34
|
lino/core/callbacks.py,sha256=xkosb1l48o6WeSdj82k5udK9OmjI7-p6x4AJFjXiOf8,7518
|
@@ -42,25 +42,25 @@ 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=wgRDDDHlEjN1el37Mgt8yvsLlLNgunr4_vSA4iFLsUM,108454
|
44
44
|
lino/core/exceptions.py,sha256=QDxDo5cllSyXQ8VWet9hGXzNadxCOmwMVrFXc6V-vpE,665
|
45
|
-
lino/core/fields.py,sha256=
|
45
|
+
lino/core/fields.py,sha256=0vK0F4LCqwwjLXA3sA7qG4jR9OvQF9EgIDVcsac9Qh0,57335
|
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=o9pHxWBuo15vpGN5pwCsWVNk2awrMuBigOHiua78v4I,13413
|
50
50
|
lino/core/kernel.py,sha256=gqx1dqVpahdxNPejLcVm9c7JX3qlajosEJ-yEQTgHCU,48275
|
51
51
|
lino/core/keyboard.py,sha256=imdO-J5npZijtddhM2C7CLo2K6Hp30egsXgOOa4-AqQ,1137
|
52
|
-
lino/core/layouts.py,sha256=
|
52
|
+
lino/core/layouts.py,sha256=Wojx5UUyhy7PsZE8FWmiXcmZDj4wz2y_1_wlz1G560Q,28663
|
53
53
|
lino/core/menus.py,sha256=BoPtcqtTB1-ADp3ffnzEXyIx8lQ4HLaZWxo0eQrj-T4,10850
|
54
54
|
lino/core/merge.py,sha256=sKtTeZtHdoDKerdHj4NXuXXNzpKDsfdPaiq-CY0NqQc,9094
|
55
55
|
lino/core/model.py,sha256=MNTlg53WbKXPIne5wOHtO5V3nLdxoYTBMosz9JdFQJU,36386
|
56
56
|
lino/core/permissions.py,sha256=Fnemz3NwWz21X0YATI9Q7ba2FcAdg-EMLHjIcbt_AVU,6840
|
57
57
|
lino/core/plugin.py,sha256=oVvTsGoBBYmjvRgtyiFPIiHZQErH0ZlNjiUFtOk2dOM,6834
|
58
58
|
lino/core/renderer.py,sha256=jIXxNSpljZhb9tBMhUfDNbZD3XmxYzaS6SlipHx29L4,47291
|
59
|
-
lino/core/requests.py,sha256=
|
59
|
+
lino/core/requests.py,sha256=DAen9Jys3RfDMRQNbQFAo_h7iUipe7khhXTVT4RvcNY,92822
|
60
60
|
lino/core/roles.py,sha256=PXwk436xUupxdbJcygRSYFu7ixfKjAJPQRUQ8sy0lB0,4425
|
61
61
|
lino/core/signals.py,sha256=0JT89mkjSbRm57QZcSI9DoThoKUGkyi-egNhuLUKEds,948
|
62
62
|
lino/core/site.py,sha256=lEPAEF4OyBsF8NLy3y9O0GOcC5C1REc9ug9mIZR-mIs,83150
|
63
|
-
lino/core/store.py,sha256=
|
63
|
+
lino/core/store.py,sha256=6B_sYwkIKuIRsibx8iRrICyqJggqHh7pMC5K3-e7k7I,51372
|
64
64
|
lino/core/tables.py,sha256=VXfUDENJ-Zl6M3tRvEdLr1LGjmJcAmwXUWSG4EWLFDE,24413
|
65
65
|
lino/core/urls.py,sha256=06QlmN1vpxjmb5snO3SPpP6lX1pMdE60bTiBiC77_vQ,2677
|
66
66
|
lino/core/user_types.py,sha256=0iSYmzr2M9v2Mn2y6hzAZeqareUT-gD7l3MfIPyG9ZI,867
|
@@ -85,8 +85,8 @@ lino/locale/es/LC_MESSAGES/django.mo,sha256=r2zi4aulC-1zX1XcoGddo0mpdOpuuOpUxpWx
|
|
85
85
|
lino/locale/es/LC_MESSAGES/django.po,sha256=JKSABlHW8LZFD6oK9Oh-gw9hwCAlfZjDg1Nl2nZUkTE,153744
|
86
86
|
lino/locale/et/LC_MESSAGES/django.mo,sha256=1RH5dX6YOBgk2tX_xpkriBRDh6qkxJDPrWysVeio_eM,5519
|
87
87
|
lino/locale/et/LC_MESSAGES/django.po,sha256=0jGqXMllcz_7-T2S-lSeR-BeTMfI4_Rgz1h5Jy_D1xE,217301
|
88
|
-
lino/locale/fr/LC_MESSAGES/django.mo,sha256=
|
89
|
-
lino/locale/fr/LC_MESSAGES/django.po,sha256=
|
88
|
+
lino/locale/fr/LC_MESSAGES/django.mo,sha256=N7TxEPKmUBjDLu-EabjGUm1VB-CqKjZH1AzRRJ2M5OM,18078
|
89
|
+
lino/locale/fr/LC_MESSAGES/django.po,sha256=xRP1JGSmqAk3IuCohb6qCtUsokA90oaEj701WX-qhJ4,162550
|
90
90
|
lino/locale/nl/LC_MESSAGES/django.mo,sha256=cQ3DTQqc4dbwrAdm5d95Kf4pDoYqKdMdElAaRerC0XA,8115
|
91
91
|
lino/locale/nl/LC_MESSAGES/django.po,sha256=u_oZzTdxdEdyMKAJfNVI3Vm1D-uKPCKYDPSXa1vn_qc,339218
|
92
92
|
lino/locale/pt/LC_MESSAGES/django.mo,sha256=OCKgnomRXLl_QsikdFsqUwKXkVexvLvSWf5kizPJrRE,42461
|
@@ -97,14 +97,14 @@ lino/locale/zh_Hant/LC_MESSAGES/django.po,sha256=KWejkd_imTiK-SX6BG_bfEGtGIWEQ-b
|
|
97
97
|
lino/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
98
98
|
lino/management/commands/__init__.py,sha256=raVDRiXns3SegyXEhaLZMcxfEDs7ggy2nFUN5D0f5F0,47
|
99
99
|
lino/management/commands/buildcache.py,sha256=QjhvKKdp1mX6rl8Y5rcS6kUK2LVOBVAd6wrUKLYSGF8,448
|
100
|
-
lino/management/commands/demotest.py,sha256=
|
100
|
+
lino/management/commands/demotest.py,sha256=543acKUeqliMSgI_21ylSMvMlMpnjJej065MdSIkzNo,4920
|
101
101
|
lino/management/commands/diag.py,sha256=vt-NlZUx5gf7T4EpbM-gle3tAwMuwfPQY8lUgxjFaUw,478
|
102
102
|
lino/management/commands/dump2py.py,sha256=DyvhXYPJY7-Tt_xyw4_U5WjVeobcOU5AhWRZB6l4esI,20329
|
103
103
|
lino/management/commands/dump_settings.py,sha256=tGOR4h_ueVe2DOk84ILFvzvndt0doshvaxRkybB-rnY,2009
|
104
104
|
lino/management/commands/initdb.py,sha256=U1yu7JoPG3sDVYmn985Z73oux1zPHl7Ur_U5UJbMBb4,11467
|
105
105
|
lino/management/commands/install.py,sha256=PljQJecr9s8rk5caR4rW0Fg1mL3S9JJHp6NqgB8bWTs,1888
|
106
106
|
lino/management/commands/makemigdump.py,sha256=TvNnFFjD6XRMFLbX8IEMSNDKTMPLTBCi8i5SRNcpYD8,1279
|
107
|
-
lino/management/commands/makescreenshots.py,sha256=
|
107
|
+
lino/management/commands/makescreenshots.py,sha256=fJF7ATZz7_s1IWkkYMEHVTLB5r5C1ny-kJp253BeoKM,8667
|
108
108
|
lino/management/commands/makeui.py,sha256=qYz68fnUKNXicZfGy3GXdjIZubhg1KyQnqjMblFN_LY,4813
|
109
109
|
lino/management/commands/mergedata.py,sha256=-dPvBtyc-AqKpQeL4TUd2IKHGe8EaaW8Citcsp_hwEU,2527
|
110
110
|
lino/management/commands/monitor.py,sha256=-axtsW-uzk87ESR6-GSfUL0Y2ylB5BwHC6Xlx3fPxo4,5113
|
@@ -180,7 +180,7 @@ lino/modlib/comments/roles.py,sha256=z3gctvlTa_5PAs-D4pounyzNyuEc31jTFq9g33r6Z1w
|
|
180
180
|
lino/modlib/comments/ui.py,sha256=w72vOmK8fn6H13t2aPS7ydYU1fCsbbMH2-TSNWt3pwA,9799
|
181
181
|
lino/modlib/comments/config/comments/comments.js,sha256=7oAnNyx_MKM1iWPu-QSp6iKfnOVdgq7EciQPpxTvYU8,242
|
182
182
|
lino/modlib/comments/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
183
|
-
lino/modlib/comments/fixtures/demo2.py,sha256=
|
183
|
+
lino/modlib/comments/fixtures/demo2.py,sha256=mi1LY0-hotH-BG34bGgvCXkvDhVJPQ4uDfzKCicSIRM,25248
|
184
184
|
lino/modlib/dashboard/__init__.py,sha256=_PFbmakUn8DShXyJY3EfAcuZtX5ofWnS-8dk7s1CrLw,1420
|
185
185
|
lino/modlib/dashboard/models.py,sha256=EgRNg88dmz-OlIdi1SyEuerWMsRqKIfqE2MgKL7kApw,3510
|
186
186
|
lino/modlib/dupable/__init__.py,sha256=fIQ8wj-T8ZbkjwQgW_-ankJsHLjPMepOTo32mJXNCvI,532
|
@@ -4388,7 +4388,7 @@ lino/modlib/tinymce/static/tinymce-4.1.10/skins/lightgray/img/loader.gif,sha256=
|
|
4388
4388
|
lino/modlib/tinymce/static/tinymce-4.1.10/skins/lightgray/img/object.gif,sha256=5qFeUrxKF7CFBzuo3r1HCOrWrj1MvrOIDGXLevxIl3c,152
|
4389
4389
|
lino/modlib/tinymce/static/tinymce-4.1.10/skins/lightgray/img/trans.gif,sha256=nPAg18O7p_WrEM2lSqvvk0-QbU-aOs-Z6efcbJhXljU,43
|
4390
4390
|
lino/modlib/tinymce/static/tinymce-4.1.10/themes/modern/theme.min.js,sha256=w41NrMzqdGEDk6OhjeuElBHlIr5Ntt_QpdoxNRFXa3Q,6431
|
4391
|
-
lino/modlib/uploads/__init__.py,sha256=
|
4391
|
+
lino/modlib/uploads/__init__.py,sha256=S6RNBs5vwCTnoAkPGRGWBQdKp1uOzWngc_B19iAmGsg,2675
|
4392
4392
|
lino/modlib/uploads/actions.py,sha256=lSdMmMmFaJRkJ2JkMX0aOVFNiisGVcI3PP3WqSQmK1E,1402
|
4393
4393
|
lino/modlib/uploads/choicelists.py,sha256=RVKLCEDly9VUa183ul5U9DRla8yOkMxrP4qMjTC5410,1327
|
4394
4394
|
lino/modlib/uploads/dummy_upload.odt,sha256=VHG2YkykCg8VqoXx8Hm37QYunvdbmg_jCyygiZseKF8,10447
|
@@ -4396,24 +4396,25 @@ lino/modlib/uploads/dummy_upload.pdf,sha256=hdAx7s3V10lqVekSGugzkn_Hqxx3V4OkCNVN
|
|
4396
4396
|
lino/modlib/uploads/mixins.py,sha256=4CSTEDU0ZBfdCV5RqV9SGc3r0rH7TlaGdB7tGGlVN-o,8000
|
4397
4397
|
lino/modlib/uploads/models.py,sha256=ATLVrV1cbmUj7Kv_pLOmBz3IkKpvYBjGriv74AkjD0M,16528
|
4398
4398
|
lino/modlib/uploads/roles.py,sha256=ae0wf_vC4O6MffDx8abpjW1M2oWOp5VzOvt_ckk72Cc,191
|
4399
|
-
lino/modlib/uploads/ui.py,sha256=
|
4399
|
+
lino/modlib/uploads/ui.py,sha256=dc17OUf8R6jqFFt6qzfCkBHIiMKEhoOBGFw0esWfA2g,8456
|
4400
4400
|
lino/modlib/uploads/utils.py,sha256=MQAJbI5sUe0RCXCrkxpNKUJFxHpz1bOMqKQy3QsA76o,3343
|
4401
4401
|
lino/modlib/uploads/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4402
|
+
lino/modlib/uploads/fixtures/demo.py,sha256=XY5oNgPvlPcL3B3nBMkqpAkfRZ0WGsr_2edOlpWTcF8,1661
|
4402
4403
|
lino/modlib/uploads/fixtures/demo3.py,sha256=q0bwZrx5XtRsRlFpsa33fL0sCl7IdCYaP9E1rhCnJt4,547
|
4403
|
-
lino/modlib/users/__init__.py,sha256=
|
4404
|
+
lino/modlib/users/__init__.py,sha256=40f-PheIyHqAzGXQbkvEKAnZ9_bb8RkaLAKIqNE96qg,3215
|
4404
4405
|
lino/modlib/users/actions.py,sha256=Nik2CoxKZWoGIsPT50mWESzHSTQx9WiBXWG64CUFyS8,18074
|
4405
4406
|
lino/modlib/users/choicelists.py,sha256=-X76C1NxIs5e7rFHp5Z0kjJkA1NlOP2vdLKGkI2wZRU,3876
|
4406
4407
|
lino/modlib/users/mixins.py,sha256=cMmTtR1-w9iWgdPlNF5kMybDR41D5kd1waGxEROSvSE,14150
|
4407
4408
|
lino/modlib/users/models.py,sha256=tdROzvtd3cMxsXKtYZjcUv2XJU7hQLbyBCiE0zVvaOo,16470
|
4408
4409
|
lino/modlib/users/roles.py,sha256=yi29ELbWU1VtteGARaxetxmsCkZQHA2oJiD0dXujMiE,320
|
4409
|
-
lino/modlib/users/ui.py,sha256=
|
4410
|
+
lino/modlib/users/ui.py,sha256=WA1bqVx1Z4yQzydHhvw_d5yE-teKdkHqd36ynz9ivPk,13127
|
4410
4411
|
lino/modlib/users/utils.py,sha256=bD0DJZsUy59xw9N-tx3W_h30_R10GT2qXZVzYtGWMa8,1963
|
4411
4412
|
lino/modlib/users/config/users/verification_response.html,sha256=8X1sEn53ploQgB6ds0UfmmkZpcvP9KSwWiQjRE_q970,772
|
4412
4413
|
lino/modlib/users/config/users/welcome_email.eml,sha256=bPSPbJKIPFRVWPDCuhNquQYwQtXzYGZgs7wICoiutS8,1078
|
4413
4414
|
lino/modlib/users/config/users/User/welcome.body.html,sha256=5k1cVYdYUd0vDLUzyRBtGy52A027wpRiGYLbdgaOKs0,141
|
4414
4415
|
lino/modlib/users/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4415
4416
|
lino/modlib/users/fixtures/demo.py,sha256=YHPhvjqAh-V9WHgFct2GQlQATZmS-W3Nry-X6mI05z8,199
|
4416
|
-
lino/modlib/users/fixtures/demo2.py,sha256=
|
4417
|
+
lino/modlib/users/fixtures/demo2.py,sha256=j2ke91wvpHs3kHpeztzV3nOG4rJvavkHv2YJo0dISdI,495
|
4417
4418
|
lino/modlib/users/fixtures/demo_users.py,sha256=FJz5gW95PbgxrPD8BMSVnpA8SJJSPWtjyi3LMdytd5o,1805
|
4418
4419
|
lino/modlib/users/fixtures/std.py,sha256=Eo_TdqFC7NPryLeGRfp-nbOXw3hDqxTUpddFTxUuZ74,712
|
4419
4420
|
lino/modlib/weasyprint/__init__.py,sha256=_kLw0xg5_ByLv4l5VvQbZjTtloTM4c9WrpfFgOGMPVc,2344
|
@@ -4604,7 +4605,7 @@ lino/utils/cycler.py,sha256=2LGMhMJX5At5ln4yZvmNleWROs-CA_YE_UCzxzvxK4U,1548
|
|
4604
4605
|
lino/utils/daemoncommand.py,sha256=NjGShiz09fddIV0WU0jK2nzO_CwPj1MfdmgwAOYZi4M,11525
|
4605
4606
|
lino/utils/dataserializer.py,sha256=-_xHXaGwDSO6-sYEHEa2BtEmKS8bW6gsYx4dV-GbvDs,3779
|
4606
4607
|
lino/utils/dates.py,sha256=eWF5WxA5uJf51Y9PKvDVBWD8yIf6yBF6oO6TeU3ujzw,1030
|
4607
|
-
lino/utils/dbfreader.py,sha256=
|
4608
|
+
lino/utils/dbfreader.py,sha256=lTIHkqmWJnKTdMwtF7amlSVBZZe2bW81fWF22Y4f5nM,12131
|
4608
4609
|
lino/utils/dblogger.py,sha256=kr0YxQY6veymvNg5A4tsvkqW8haRWdwqL0C-_9_QTg0,721
|
4609
4610
|
lino/utils/diag.py,sha256=evkU818hZSGpWdL0Du11QakT5_frvc5z4C93IEBlECg,18307
|
4610
4611
|
lino/utils/djangotest.py,sha256=Phz1qNp0wDonZRja5dxbCk0Xl3a73gZNiKK8v9tAgZg,8334
|
@@ -4648,8 +4649,8 @@ lino/utils/xml.py,sha256=4Z44W1e5HvTVrU8erkohgnwqY-5Cr2NHywaAJ5OgRvw,989
|
|
4648
4649
|
lino/utils/mldbc/__init__.py,sha256=QqWRlzeXaOmFfbCk-vTY3SZMn1-FCf67XnpZdd_Nim0,1134
|
4649
4650
|
lino/utils/mldbc/fields.py,sha256=tAX8G5UKigr9c6g0F3ARIjZZtg406mdaZ--PWSbiH9E,2873
|
4650
4651
|
lino/utils/mldbc/mixins.py,sha256=CkYe5jDa7xp9fJq_V8zcZf8ocxgIjUgHc9KZccvA_Yw,1945
|
4651
|
-
lino-25.1.
|
4652
|
-
lino-25.1.
|
4653
|
-
lino-25.1.
|
4654
|
-
lino-25.1.
|
4655
|
-
lino-25.1.
|
4652
|
+
lino-25.1.5.dist-info/METADATA,sha256=wGSveOojnYjUFx-8Ag72a9SoTwNUYFaaJ-Ce9LfUzPA,42534
|
4653
|
+
lino-25.1.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
4654
|
+
lino-25.1.5.dist-info/licenses/AUTHORS.rst,sha256=8VEm_G4HOmYEa4oi1nVoKKsdo4JanekEJCefWd2E8vk,981
|
4655
|
+
lino-25.1.5.dist-info/licenses/COPYING,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
|
4656
|
+
lino-25.1.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|