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 CHANGED
@@ -26,7 +26,7 @@ defines no models, some template files, a series of :term:`django-admin commands
26
26
 
27
27
  """
28
28
 
29
- __version__ = '25.1.3'
29
+ __version__ = '25.1.5'
30
30
 
31
31
  # import setuptools # avoid UserWarning "Distutils was imported before Setuptools"?
32
32
 
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
- de = self._datasource.get_data_elem(name)
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 is not None and ContentType is not None:
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
- kw.update(
2127
- param_values=self.actor.params_layout.params_store.pv2dict(
2128
- self, self.param_values
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
- self.param_fields = []
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
- self.param_fields.append(sf)
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(self.param_fields)
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: 2024-11-16 21:42+0200\n"
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 "à propos"
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=1234")
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, "1234")
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("1234"), "Too many authentication failures from 127.0.0.1"
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("1234"), "Now signed in as Robin Rood")
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-2013 Luc Saffre
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="1234")
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. With an 👁 (U+1F441)."
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
- if dd.is_installed("contacts"):
47
- BODIES.items.append("")
48
- MENTIONED = Cycler()
49
- MENTIONED.items += list(rt.models.contacts.Person.objects.all())
50
- MENTIONED.items += list(rt.models.contacts.Company.objects.all())
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
- cmd1 = MENTIONED.pop().obj2memo()
76
- cmd2 = MENTIONED.pop().obj2memo()
77
- body = f"This is a comment about {cmd1} and {cmd2}."
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)
@@ -29,13 +29,11 @@ class Plugin(ad.Plugin):
29
29
  """Whether to use PIL, the Python Imaging Library.
30
30
  """
31
31
 
32
- # def on_ui_init(self, kernel):
33
- # super().on_ui_init(kernel)
34
- # self.site.makedirs_if_missing(self.get_uploads_root())
35
- # self.site.makedirs_if_missing(self.get_volumes_root())
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 description id *"
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,
@@ -21,6 +21,7 @@ class Plugin(ad.Plugin):
21
21
  with_nickname = False
22
22
  # partner_model = 'contacts.Person'
23
23
  partner_model = "contacts.Partner"
24
+ demo_password = "1234"
24
25
 
25
26
  def pre_site_startup(self, site):
26
27
  super().pre_site_startup(site)
@@ -1,17 +1,18 @@
1
1
  # -*- coding: UTF-8 -*-
2
- # Copyright 2012-2014 Rumma & Ko Ltd
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 "1234" for all users.
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("1234")
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-2023 Rumma & Ko Ltd
2
+ # Copyright 2011-2025 Rumma & Ko Ltd
3
3
  # License: GNU Affero General Public License v3 (see file COPYING for details)
4
- """Desktop UI for this plugin.
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="1234")
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 __future__ import print_function
16
- from builtins import hex
17
- from builtins import str
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
- return ord(number[0]) + 256 * (
36
- ord(number[1]) + 256 * (ord(number[2]) + 256 * ord(number[3]))
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 ord(number[3]) + 256 * (
42
- ord(number[2]) + 256 * (ord(number[1]) + 256 * ord(number[0]))
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 ord(number[0]) + 256 * ord(number[1])
47
+ return number[0] + 256 * number[1]
48
48
 
49
49
 
50
50
  def unpack_int_rev(number):
51
- return ord(number[1]) + 256 * ord(number[0])
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(ord(ch)), ch, ord(ch)))
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
- "\x03": "dBASE III",
80
- "\x83": "dBASE III+ with memo",
81
- "\x8B": "dBASE IV with memo",
82
- "\xF5": "FoxPro with memo",
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 = ord(header[1]) + 2000
96
- month = ord(header[2])
97
- day = ord(header[3])
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 == "\x0D":
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 == "\x83":
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 ord(self.version) & self.HAS_MEMO_FILE:
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 = string.find(buf, "\x00")
258
+ pos = buf.find(0)
263
259
  if pos == -1 or pos > 11:
264
260
  pos = 11
265
- self.name = buf[:pos]
266
- self.field_type = buf[11]
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 = ord(buf[16])
269
- self.field_places = ord(buf[17])
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
- # if len(buf) != self.blocksize:
379
- # print str(number)+":"+str(len(buf))
380
- ## data += buf
381
- # break
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("\x1A")
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 not self.dbf.codepage is None:
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
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=eVK8Gig7mM7P3h6tu-4vlJJZfxRPM3rYL8q6QMl-mss,5584
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=_DIvjr1gb6Z29mqWcwv6snZ8MOiWdZSoBIiCViQndk8,46311
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=3h4FFVvWDncXAlOAsLvPalXjpSSZed_49M7Fp183uRw,57273
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=vMoSwgNK-G4vOF5pcs5OhS73Q3YOvuVlCC1LgoIzb-Y,28509
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=6CJumCg4Ds4k7XNPTEdDJOZHOKhVyyqmNxAZkduLau8,92542
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=UOUcVsjt61QrZ9QHy2P2rC_9Q8R-d0JAXLH0Ps41YQ4,51341
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=xOUuHwSjJ4AqMWuI6YHCfach3CKEKkt1l4KR_-YjBR4,17925
89
- lino/locale/fr/LC_MESSAGES/django.po,sha256=fBojP3hqMYF3cxQfgJioApQV9DQXo-YeA866kfaWGwg,162522
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=xnqRRFvKZ94pcWSlepFFAR7ycC4c2ppWqSRsSGj__Ac,4844
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=VkTMmlRzG8JyxQne3bDm4ONXY5-dW0RmiJZvbbOGEDo,8615
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=zlNaLCyG44HvQ6kKU1emiArT2z7O1nYGiovYh9DyHmM,24396
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=vM3gC8xZ-JdOf1EuNipJyHIhg5V8rLLWCPWTCKLp5aU,2830
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=Iu06xyKaTKbw2YfTgDJYWQVXuUuVAqENgnfnscViL_c,8456
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=QHLCNKiRMyL14Iy2eiz7_y9fAwugnDCt4N0aKtIhFA8,3188
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=kRuCCEK77ZhHj3kawio6NTcAvEixwupKkVnQ5LByCEc,13143
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=4-toQfGIkJF8eROS1FgBxP6w-EiKOI7QBoHcIO2T0dw,420
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=oV-8yQZo6MZlb_Y2DZPGx3y8tDeRo2d8RWhZzz1i7E8,11805
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.3.dist-info/METADATA,sha256=w5X-HBjx45X4cvs5dxXVGxbh4zw95cibk9VIxPvidzY,42534
4652
- lino-25.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
4653
- lino-25.1.3.dist-info/licenses/AUTHORS.rst,sha256=8VEm_G4HOmYEa4oi1nVoKKsdo4JanekEJCefWd2E8vk,981
4654
- lino-25.1.3.dist-info/licenses/COPYING,sha256=DZak_2itbUtvHzD3E7GNUYSRK6jdOJ-GqncQ2weavLA,34523
4655
- lino-25.1.3.dist-info/RECORD,,
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