lino 24.11.1__py3-none-any.whl → 25.1.0__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.
Files changed (51) hide show
  1. lino/__init__.py +1 -1
  2. lino/core/actors.py +33 -12
  3. lino/core/fields.py +26 -18
  4. lino/core/kernel.py +4 -6
  5. lino/core/model.py +5 -16
  6. lino/core/renderer.py +1 -2
  7. lino/core/requests.py +70 -47
  8. lino/core/site.py +1 -1
  9. lino/core/tables.py +0 -16
  10. lino/help_texts.py +4 -3
  11. lino/locale/bn/LC_MESSAGES/django.po +58 -45
  12. lino/locale/de/LC_MESSAGES/django.mo +0 -0
  13. lino/locale/de/LC_MESSAGES/django.po +79 -108
  14. lino/locale/django.pot +55 -44
  15. lino/locale/es/LC_MESSAGES/django.po +56 -44
  16. lino/locale/et/LC_MESSAGES/django.po +58 -45
  17. lino/locale/fr/LC_MESSAGES/django.mo +0 -0
  18. lino/locale/fr/LC_MESSAGES/django.po +60 -48
  19. lino/locale/nl/LC_MESSAGES/django.po +59 -45
  20. lino/locale/pt_BR/LC_MESSAGES/django.po +55 -44
  21. lino/locale/zh_Hant/LC_MESSAGES/django.po +55 -44
  22. lino/mixins/dupable.py +8 -7
  23. lino/mixins/periods.py +4 -4
  24. lino/modlib/checkdata/__init__.py +1 -1
  25. lino/modlib/comments/ui.py +7 -3
  26. lino/modlib/dupable/models.py +10 -14
  27. lino/modlib/gfks/mixins.py +8 -1
  28. lino/modlib/jinja/choicelists.py +3 -3
  29. lino/modlib/jinja/renderer.py +2 -0
  30. lino/modlib/languages/fixtures/all_languages.py +4 -6
  31. lino/modlib/memo/mixins.py +7 -7
  32. lino/modlib/memo/models.py +41 -12
  33. lino/modlib/memo/parser.py +7 -3
  34. lino/modlib/notify/mixins.py +8 -8
  35. lino/modlib/periods/choicelists.py +46 -0
  36. lino/modlib/periods/mixins.py +26 -0
  37. lino/modlib/periods/models.py +17 -45
  38. lino/modlib/publisher/choicelists.py +1 -4
  39. lino/modlib/uploads/mixins.py +37 -37
  40. lino/modlib/uploads/models.py +68 -18
  41. lino/modlib/uploads/utils.py +6 -0
  42. lino/modlib/users/mixins.py +9 -6
  43. lino/modlib/weasyprint/choicelists.py +17 -7
  44. lino/utils/choosers.py +21 -8
  45. lino/utils/instantiator.py +9 -0
  46. lino/utils/soup.py +5 -5
  47. {lino-24.11.1.dist-info → lino-25.1.0.dist-info}/METADATA +4 -2
  48. {lino-24.11.1.dist-info → lino-25.1.0.dist-info}/RECORD +51 -50
  49. {lino-24.11.1.dist-info → lino-25.1.0.dist-info}/WHEEL +1 -1
  50. {lino-24.11.1.dist-info → lino-25.1.0.dist-info}/licenses/AUTHORS.rst +0 -0
  51. {lino-24.11.1.dist-info → lino-25.1.0.dist-info}/licenses/COPYING +0 -0
@@ -7,7 +7,7 @@ msgid ""
7
7
  msgstr ""
8
8
  "Project-Id-Version: lino 24.7.0\n"
9
9
  "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
10
- "POT-Creation-Date: 2024-11-15 13:05+0200\n"
10
+ "POT-Creation-Date: 2024-11-16 21:41+0200\n"
11
11
  "PO-Revision-Date: 2024-07-20 19:57+0300\n"
12
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
13
  "Language: zh_Hant\n"
@@ -3539,8 +3539,8 @@ msgstr ""
3539
3539
  #: lino/modlib/importfilters/models.py:100 lino/modlib/notify/actions.py:14
3540
3540
  #: lino/modlib/search/models.py:85 lino/modlib/system/mixins.py:286
3541
3541
  #: lino/modlib/tinymce/models.py:21 lino/modlib/uploads/actions.py:23
3542
- #: lino/modlib/uploads/models.py:49 lino/modlib/uploads/models.py:121
3543
- #: lino/modlib/uploads/models.py:193 lino/modlib/users/ui.py:262
3542
+ #: lino/modlib/uploads/models.py:53 lino/modlib/uploads/models.py:125
3543
+ #: lino/modlib/uploads/models.py:189 lino/modlib/users/ui.py:262
3544
3544
  msgid "Description"
3545
3545
  msgstr ""
3546
3546
 
@@ -3613,7 +3613,7 @@ msgstr ""
3613
3613
  msgid "Select a %s..."
3614
3614
  msgstr ""
3615
3615
 
3616
- #: lino/core/elems.py:1618 lino/modlib/uploads/models.py:377
3616
+ #: lino/core/elems.py:1618 lino/modlib/uploads/models.py:380
3617
3617
  msgid "show"
3618
3618
  msgstr ""
3619
3619
 
@@ -4936,12 +4936,12 @@ msgid "Controlled by"
4936
4936
  msgstr ""
4937
4937
 
4938
4938
  #: lino/modlib/gfks/mixins.py:31 lino/modlib/gfks/mixins.py:53
4939
- #: lino/modlib/memo/models.py:36
4939
+ #: lino/modlib/memo/models.py:37
4940
4940
  msgid "(type)"
4941
4941
  msgstr ""
4942
4942
 
4943
4943
  #: lino/modlib/gfks/mixins.py:39 lino/modlib/gfks/mixins.py:49
4944
- #: lino/modlib/memo/models.py:44
4944
+ #: lino/modlib/memo/models.py:45
4945
4945
  msgid "(object)"
4946
4946
  msgstr ""
4947
4947
 
@@ -5256,19 +5256,26 @@ msgstr ""
5256
5256
  msgid "Mentions differ from expected mentions."
5257
5257
  msgstr ""
5258
5258
 
5259
- #: lino/modlib/memo/models.py:20 lino/modlib/uploads/models.py:250
5260
- #: lino/modlib/uploads/models.py:264
5261
- msgid "Source"
5259
+ #: lino/modlib/memo/models.py:21
5260
+ msgid "Target"
5262
5261
  msgstr ""
5263
5262
 
5264
- #: lino/modlib/memo/models.py:27
5263
+ #: lino/modlib/memo/models.py:28
5265
5264
  msgid "Mention"
5266
5265
  msgstr ""
5267
5266
 
5268
- #: lino/modlib/memo/models.py:28
5267
+ #: lino/modlib/memo/models.py:29
5269
5268
  msgid "Mentions"
5270
5269
  msgstr ""
5271
5270
 
5271
+ #: lino/modlib/memo/models.py:62
5272
+ msgid "Referrer"
5273
+ msgstr ""
5274
+
5275
+ #: lino/modlib/memo/models.py:81
5276
+ msgid "Mentioned by"
5277
+ msgstr ""
5278
+
5272
5279
  #: lino/modlib/notify/__init__.py:16
5273
5280
  msgid "Messages"
5274
5281
  msgstr ""
@@ -5711,7 +5718,7 @@ msgstr ""
5711
5718
  msgid "You have a dangling edit lock on"
5712
5719
  msgstr ""
5713
5720
 
5714
- #: lino/modlib/system/actions.py:17 lino/modlib/uploads/models.py:389
5721
+ #: lino/modlib/system/actions.py:17 lino/modlib/uploads/models.py:392
5715
5722
  msgid "Edit"
5716
5723
  msgstr ""
5717
5724
 
@@ -6144,116 +6151,120 @@ msgstr ""
6144
6151
  msgid "File size"
6145
6152
  msgstr ""
6146
6153
 
6147
- #: lino/modlib/uploads/models.py:42
6154
+ #: lino/modlib/uploads/models.py:46
6148
6155
  msgid "Library volume"
6149
6156
  msgstr ""
6150
6157
 
6151
- #: lino/modlib/uploads/models.py:43
6158
+ #: lino/modlib/uploads/models.py:47
6152
6159
  msgid "Library volumes"
6153
6160
  msgstr ""
6154
6161
 
6155
- #: lino/modlib/uploads/models.py:47
6162
+ #: lino/modlib/uploads/models.py:51
6156
6163
  msgid "Root directory"
6157
6164
  msgstr ""
6158
6165
 
6159
- #: lino/modlib/uploads/models.py:80
6166
+ #: lino/modlib/uploads/models.py:84
6160
6167
  msgid "Upload type"
6161
6168
  msgstr ""
6162
6169
 
6163
- #: lino/modlib/uploads/models.py:81
6170
+ #: lino/modlib/uploads/models.py:85
6164
6171
  msgid "Upload types"
6165
6172
  msgstr ""
6166
6173
 
6167
- #: lino/modlib/uploads/models.py:86
6174
+ #: lino/modlib/uploads/models.py:90
6168
6175
  msgid "Max. number"
6169
6176
  msgstr ""
6170
6177
 
6171
- #: lino/modlib/uploads/models.py:94
6178
+ #: lino/modlib/uploads/models.py:98
6172
6179
  msgid "No need to upload more uploads than N of this type."
6173
6180
  msgstr ""
6174
6181
 
6175
- #: lino/modlib/uploads/models.py:95
6182
+ #: lino/modlib/uploads/models.py:99
6176
6183
  msgid "-1 means no limit."
6177
6184
  msgstr ""
6178
6185
 
6179
- #: lino/modlib/uploads/models.py:99
6186
+ #: lino/modlib/uploads/models.py:103
6180
6187
  msgid "Wanted"
6181
6188
  msgstr ""
6182
6189
 
6183
- #: lino/modlib/uploads/models.py:101
6190
+ #: lino/modlib/uploads/models.py:105
6184
6191
  msgid "Add a (+) button when there is no upload of this type."
6185
6192
  msgstr ""
6186
6193
 
6187
- #: lino/modlib/uploads/models.py:112
6194
+ #: lino/modlib/uploads/models.py:116
6188
6195
  msgid "Upload file"
6189
6196
  msgstr ""
6190
6197
 
6191
- #: lino/modlib/uploads/models.py:113
6198
+ #: lino/modlib/uploads/models.py:117
6192
6199
  msgid "Upload files"
6193
6200
  msgstr ""
6194
6201
 
6195
- #: lino/modlib/uploads/models.py:120
6202
+ #: lino/modlib/uploads/models.py:124
6196
6203
  msgid "Library file"
6197
6204
  msgstr ""
6198
6205
 
6199
- #: lino/modlib/uploads/models.py:155
6206
+ #: lino/modlib/uploads/models.py:160
6200
6207
  msgid "Uploaded an {obj}."
6201
6208
  msgstr ""
6202
6209
 
6203
- #: lino/modlib/uploads/models.py:230
6210
+ #: lino/modlib/uploads/models.py:233
6204
6211
  msgid "No preview available"
6205
6212
  msgstr ""
6206
6213
 
6207
- #: lino/modlib/uploads/models.py:234
6214
+ #: lino/modlib/uploads/models.py:237
6208
6215
  msgid "Thumbnail"
6209
6216
  msgstr ""
6210
6217
 
6211
- #: lino/modlib/uploads/models.py:273
6218
+ #: lino/modlib/uploads/models.py:253 lino/modlib/uploads/models.py:267
6219
+ msgid "Source"
6220
+ msgstr ""
6221
+
6222
+ #: lino/modlib/uploads/models.py:276
6212
6223
  msgid "Uploaded by"
6213
6224
  msgstr ""
6214
6225
 
6215
- #: lino/modlib/uploads/models.py:274
6226
+ #: lino/modlib/uploads/models.py:277
6216
6227
  msgid "Attached to"
6217
6228
  msgstr ""
6218
6229
 
6219
- #: lino/modlib/uploads/models.py:278
6230
+ #: lino/modlib/uploads/models.py:281
6220
6231
  msgid "Check metadata of upload files"
6221
6232
  msgstr ""
6222
6233
 
6223
- #: lino/modlib/uploads/models.py:286
6234
+ #: lino/modlib/uploads/models.py:289
6224
6235
  msgid "Upload entry {} has no file"
6225
6236
  msgstr ""
6226
6237
 
6227
- #: lino/modlib/uploads/models.py:303
6238
+ #: lino/modlib/uploads/models.py:306
6228
6239
  msgid "Find orphaned files in uploads folder"
6229
6240
  msgstr ""
6230
6241
 
6231
- #: lino/modlib/uploads/models.py:319
6242
+ #: lino/modlib/uploads/models.py:322
6232
6243
  msgid "File {} has no upload entry."
6233
6244
  msgstr ""
6234
6245
 
6235
- #: lino/modlib/uploads/models.py:365
6246
+ #: lino/modlib/uploads/models.py:368
6236
6247
  msgid "Upload"
6237
6248
  msgstr ""
6238
6249
 
6239
- #: lino/modlib/uploads/models.py:367
6250
+ #: lino/modlib/uploads/models.py:370
6240
6251
  msgid "Upload a file from your PC to the server."
6241
6252
  msgstr ""
6242
6253
 
6243
- #: lino/modlib/uploads/models.py:381
6254
+ #: lino/modlib/uploads/models.py:384
6244
6255
  msgid "Open the uploaded file in a new browser window"
6245
6256
  msgstr ""
6246
6257
 
6247
- #: lino/modlib/uploads/models.py:391 lino/modlib/uploads/ui.py:204
6258
+ #: lino/modlib/uploads/models.py:394 lino/modlib/uploads/ui.py:204
6248
6259
  msgid "Edit metadata of the uploaded file."
6249
6260
  msgstr ""
6250
6261
 
6251
- #: lino/modlib/uploads/models.py:396
6262
+ #: lino/modlib/uploads/models.py:399
6252
6263
  msgctxt "uploaded file"
6253
6264
  msgid "Last"
6254
6265
  msgstr ""
6255
6266
 
6256
- #: lino/modlib/uploads/models.py:402
6267
+ #: lino/modlib/uploads/models.py:405
6257
6268
  msgid "All {0} files"
6258
6269
  msgstr ""
6259
6270
 
@@ -6261,19 +6272,19 @@ msgstr ""
6261
6272
  msgid "Open the file in a new browser window"
6262
6273
  msgstr ""
6263
6274
 
6264
- #: lino/modlib/uploads/utils.py:37
6275
+ #: lino/modlib/uploads/utils.py:43
6265
6276
  msgid "PDF file"
6266
6277
  msgstr ""
6267
6278
 
6268
- #: lino/modlib/uploads/utils.py:39
6279
+ #: lino/modlib/uploads/utils.py:45
6269
6280
  msgid "picture"
6270
6281
  msgstr ""
6271
6282
 
6272
- #: lino/modlib/uploads/utils.py:40
6283
+ #: lino/modlib/uploads/utils.py:46
6273
6284
  msgid "media file"
6274
6285
  msgstr ""
6275
6286
 
6276
- #: lino/modlib/uploads/utils.py:83
6287
+ #: lino/modlib/uploads/utils.py:89
6277
6288
  msgid "Must build thumbnail for {}"
6278
6289
  msgstr ""
6279
6290
 
lino/mixins/dupable.py CHANGED
@@ -9,7 +9,7 @@ Don't mix up this module with :mod:`lino.mixins.duplicable`. Models
9
9
  are "duplicable" if users may *want* to duplicate some instance
10
10
  thereof, while "dupable" implies that the duplicates are *unwanted*.
11
11
  To dupe *somebody* means "to make a dupe of; deceive; delude; trick."
12
- (`reference.com <http://dictionary.reference.com/browse/dupe>`_), and
12
+ (`reference.com <https://dictionary.reference.com/browse/dupe>`_), and
13
13
  to dupe *something* means to duplicate it (eventually in order to
14
14
  cheat somebody e.g. by making a cheap copy of a valuable object).
15
15
 
@@ -31,9 +31,6 @@ in Python
31
31
  by Frank Hofmann (2018-02-12)
32
32
  """
33
33
 
34
- import six
35
- from builtins import map
36
-
37
34
  from django.conf import settings
38
35
  from django.db import models
39
36
 
@@ -76,6 +73,10 @@ class CheckedSubmitInsert(SubmitInsert):
76
73
  else:
77
74
  ok(ar)
78
75
 
76
+ # TODO: remove duplicate code. PhoneticWordBase.reduce_word() is exactly the
77
+ # same code as lino.modlib.dupable.models.PhoneticWord.reduce_word(). One of
78
+ # them is used in welfare, the other in avanti.
79
+
79
80
 
80
81
  class PhoneticWordBase(dd.Model):
81
82
  """Base class for the table of phonetic words of a given dupable
@@ -88,7 +89,7 @@ class PhoneticWordBase(dd.Model):
88
89
 
89
90
  """
90
91
 
91
- class Meta(object):
92
+ class Meta:
92
93
  abstract = True
93
94
 
94
95
  allow_cascaded_delete = ["owner"]
@@ -118,7 +119,7 @@ class PhoneticWordBase(dd.Model):
118
119
  dms = dm[0] or dm[1]
119
120
  if dms is None:
120
121
  return ""
121
- if isinstance(dms, six.binary_type):
122
+ if isinstance(dms, bytes):
122
123
  dms = dms.decode("utf8")
123
124
  return dms
124
125
 
@@ -141,7 +142,7 @@ class Dupable(dd.Model):
141
142
  :mod:`lino_welfare.modlib.dupable_clients`
142
143
  """
143
144
 
144
- class Meta(object):
145
+ class Meta:
145
146
  abstract = True
146
147
 
147
148
  submit_insert = CheckedSubmitInsert()
lino/mixins/periods.py CHANGED
@@ -7,10 +7,10 @@ Defines classes related to date ranges.
7
7
 
8
8
  import datetime
9
9
 
10
- try:
11
- import pytz
12
- except ImportError:
13
- pytz = None
10
+ # try:
11
+ # import pytz
12
+ # except ImportError:
13
+ # pytz = None
14
14
 
15
15
  from django.db import models
16
16
  from django.conf import settings
@@ -64,7 +64,7 @@ class Plugin(ad.Plugin):
64
64
 
65
65
  """
66
66
  super().on_plugins_loaded(site)
67
- if site.is_demo_site:
67
+ if site.is_demo_site and self.responsible_user is None:
68
68
  self.configure(responsible_user="robin")
69
69
 
70
70
  def post_site_startup(self, site):
@@ -55,9 +55,12 @@ class CommentDetail(dd.DetailLayout):
55
55
  body #body_full_preview
56
56
  """
57
57
  general2 = """
58
- reply
59
58
  RepliesByComment
59
+ reply
60
60
  """
61
+ # i moved the reply field to the bottom because i stopped using it after
62
+ # repeated cases where my editing got lost because there was a traceback
63
+ # after hitting submit, and these tracebacks are difficult to reproduce.
61
64
 
62
65
  more = dd.Panel(
63
66
  """
@@ -120,7 +123,8 @@ class Comments(dd.Table):
120
123
 
121
124
  @classmethod
122
125
  def comments_created(cls, user, sd, ed):
123
- pv = dict(start_date=sd, end_date=ed, observed_event=CommentEvents.created)
126
+ pv = dict(user=user, start_date=sd, end_date=ed, observed_event=CommentEvents.created)
127
+ # pv = dict(start_date=sd, end_date=ed, observed_event=CommentEvents.created)
124
128
  return cls.request(user=user, param_values=pv)
125
129
 
126
130
  # @classmethod
@@ -268,7 +272,7 @@ class CommentsByMentioned(CommentsByX):
268
272
  Mention = rt.models.memo.Mention
269
273
  assert not cls.model._meta.abstract
270
274
  ct = ContentType.objects.get_for_model(cls.model)
271
- mkw = gfk2lookup(Mention.source, mi, owner_type=ct)
275
+ mkw = gfk2lookup(Mention.target, mi, owner_type=ct)
272
276
  mentions = Mention.objects.filter(**mkw).values_list("owner_id", flat=True)
273
277
  # mentions = [o.comment_id for o in Mention.objects.filter(**mkw)]
274
278
  # print(mkw, mentions)
@@ -8,7 +8,7 @@ Don't mix up this module with :mod:`lino.mixins.duplicable`. Models
8
8
  are "duplicable" if users may *want* to duplicate some instance
9
9
  thereof, while "dupable" implies that the duplicates are *unwanted*.
10
10
  To dupe *somebody* means "to make a dupe of; deceive; delude; trick."
11
- (`reference.com <http://dictionary.reference.com/browse/dupe>`_), and
11
+ (`reference.com <https://dictionary.reference.com/browse/dupe>`_), and
12
12
  to dupe *something* means to duplicate it (eventually in order to
13
13
  cheat somebody e.g. by making a cheap copy of a valuable object).
14
14
 
@@ -23,15 +23,11 @@ and the `Double Metaphone
23
23
  <https://en.wikipedia.org/wiki/Metaphone#Double_Metaphone>`_
24
24
  algorithm. Read also Doug Hellmann about `Using Fuzzy Matching to
25
25
  Search by Sound with Python
26
- <http://www.informit.com/articles/article.aspx?p=1848528>`_
26
+ <https://www.informit.com/articles/article.aspx?p=1848528>`_
27
27
  (2012-03-22).
28
28
 
29
29
  """
30
30
 
31
- from __future__ import unicode_literals
32
- import six
33
- from builtins import object
34
-
35
31
  from django.db import models
36
32
 
37
33
  from lino.api import dd, _
@@ -54,7 +50,7 @@ class PhoneticWord(Controllable):
54
50
 
55
51
  """
56
52
 
57
- class Meta(object):
53
+ class Meta:
58
54
  verbose_name = _("Phonetic word")
59
55
  verbose_name_plural = _("Phonetic words")
60
56
 
@@ -86,16 +82,16 @@ class PhoneticWord(Controllable):
86
82
  dms = dm[0] or dm[1]
87
83
  if dms is None:
88
84
  return ""
89
- if isinstance(dms, six.binary_type):
85
+ if isinstance(dms, bytes):
90
86
  dms = dms.decode("utf8")
91
87
  return dms
92
88
 
93
- @classmethod
94
- def get_simple_parameters(cls):
95
- for p in super(PhoneticWord, cls).get_simple_parameters():
96
- yield p
97
- yield "owner_id"
98
- yield "owner_type"
89
+ # @classmethod
90
+ # def get_simple_parameters(cls):
91
+ # for p in super(PhoneticWord, cls).get_simple_parameters():
92
+ # yield p
93
+ # yield "owner_id"
94
+ # yield "owner_type"
99
95
 
100
96
 
101
97
  class PhoneticWords(dd.Table):
@@ -56,7 +56,7 @@ class Controllable(dd.Model):
56
56
  def update_owned_instance(self, controllable):
57
57
  if self.owner:
58
58
  self.owner.update_owned_instance(controllable)
59
- super(Controllable, self).update_owned_instance(controllable)
59
+ super().update_owned_instance(controllable)
60
60
 
61
61
  def save(self, *args, **kw):
62
62
  if settings.SITE.loading_from_dump:
@@ -72,3 +72,10 @@ class Controllable(dd.Model):
72
72
  gfk = self._meta.get_field("owner")
73
73
  kwargs = gfk2lookup(gfk, self, **kwargs)
74
74
  return model.objects.filter(**kwargs)
75
+
76
+ @classmethod
77
+ def get_simple_parameters(cls):
78
+ for p in super().get_simple_parameters():
79
+ yield p
80
+ yield "owner_type"
81
+ yield "owner_id"
@@ -37,8 +37,8 @@ class JinjaBuildMethod(DjangoBuildMethod):
37
37
  )
38
38
  context = elem.get_printable_context(ar)
39
39
  html = tpl.render(context)
40
- self.html2file(html, filename)
40
+ self.html2file(html, filename, context)
41
41
  return os.path.getmtime(filename)
42
42
 
43
- def html2file(self, html, filename):
44
- raise NotImplementedError()
43
+ def html2file(self, html, filename, context):
44
+ open(filename, "w").write(html)
@@ -128,6 +128,8 @@ class JinjaRenderer(HtmlRenderer):
128
128
  iif=iif,
129
129
  str=str,
130
130
  len=len,
131
+ int=int,
132
+ round=round,
131
133
  E=E,
132
134
  tostring=tostring,
133
135
  isinstance=isinstance,
@@ -1,5 +1,5 @@
1
1
  # -*- coding: UTF-8 -*-
2
- # Copyright 2011-2020 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
4
  """
5
5
  Adds all languages of the world to your database.
@@ -22,8 +22,6 @@ import codecs
22
22
 
23
23
  from django.conf import settings
24
24
 
25
- # from lino.utils import dblogger as logger
26
-
27
25
  from lino.api import dd
28
26
  from lino.modlib.languages.models import Language
29
27
 
@@ -752,7 +750,7 @@ def objects():
752
750
  if ln:
753
751
  ln = ln.strip()
754
752
  if not ln[-4:-3].isspace():
755
- logger.warning("german %d: syntax", n)
753
+ dd.logger.warning("german %d: syntax", n)
756
754
  else:
757
755
  code = ln[-3:]
758
756
  name = ln[:-4]
@@ -772,7 +770,7 @@ def objects():
772
770
  ln = ln.strip()
773
771
  rec = ln.split("\t")
774
772
  if len(rec) < 6:
775
- logger.warning("Ignored french:%d:%s (len(rec) is %d)", n, ln, len(rec))
773
+ dd.logger.warning("Ignored french:%d:%s (len(rec) is %d)", n, ln, len(rec))
776
774
  code = rec[1]
777
775
  if len(code) == 7:
778
776
  if code[3:4] == "/":
@@ -794,7 +792,7 @@ def objects():
794
792
  kw.update(iso2=iso2)
795
793
  yield Language(id=code, **kw)
796
794
  else:
797
- logger.debug(
795
+ dd.logger.debug(
798
796
  "%r : no name for default site language %s",
799
797
  code,
800
798
  settings.SITE.DEFAULT_LANGUAGE.django_code,
@@ -171,24 +171,24 @@ class BasePreviewable(dd.Model):
171
171
  )
172
172
  short = truncate_comment(full, self.get_preview_length())
173
173
  if not full.startswith("<"):
174
- if markdown is not None:
174
+ if dd.get_plugin_setting("memo", "use_markup"):
175
175
  full = markdown.markdown(full, **MARKDOWNCFG)
176
176
  return (short, full)
177
177
 
178
178
  def get_saved_mentions(self):
179
179
  Mention = rt.models.memo.Mention
180
180
  flt = gfk2lookup(Mention.owner, self)
181
- return Mention.objects.filter(**flt).order_by("source_type", "source_id")
181
+ return Mention.objects.filter(**flt).order_by("target_type", "target_id")
182
182
 
183
183
  def synchronize_mentions(self, mentions):
184
184
  Mention = rt.models.memo.Mention
185
185
  for obj in self.get_saved_mentions():
186
- if obj.source in mentions:
187
- mentions.remove(obj.source)
186
+ if obj.target in mentions:
187
+ mentions.remove(obj.target)
188
188
  else:
189
189
  obj.delete()
190
- for source in mentions:
191
- obj = Mention(owner=self, source=source)
190
+ for target in mentions:
191
+ obj = Mention(owner=self, target=target)
192
192
  # source_id=source.pk,
193
193
  # source_type=ContentType.objects.get_for_model(source.__class__))
194
194
  obj.full_clean()
@@ -274,7 +274,7 @@ class PreviewableChecker(Checker):
274
274
  ):
275
275
  yield (True, _("Preview differs from source."))
276
276
  is_broken = True
277
- found_mentions = set([obj.source for obj in obj.get_saved_mentions()])
277
+ found_mentions = set([obj.target for obj in obj.get_saved_mentions()])
278
278
  if expected_mentions != found_mentions:
279
279
  yield (True, _("Mentions differ from expected mentions."))
280
280
  is_broken = True
@@ -9,6 +9,7 @@ from django.utils.text import format_lazy
9
9
 
10
10
  # from rstgen.sphinxconf.sigal_image import line2html
11
11
  from lino.api import dd, rt, _
12
+ from lino.core import constants
12
13
  from lino.core.roles import SiteStaff
13
14
  from lino.core.gfks import gfk2lookup
14
15
  from lino.modlib.gfks.mixins import Controllable
@@ -17,7 +18,7 @@ from .parser import split_name_rest
17
18
  # from .mixins import *
18
19
 
19
20
  # Translators: will also be concatenated with '(type)' '(object)'
20
- source_label = _("Source")
21
+ target_label = _("Target")
21
22
 
22
23
 
23
24
  class Mention(Controllable):
@@ -27,36 +28,64 @@ class Mention(Controllable):
27
28
  verbose_name = _("Mention")
28
29
  verbose_name_plural = _("Mentions")
29
30
 
30
- source_type = dd.ForeignKey(
31
+ target_type = dd.ForeignKey(
31
32
  ContentType,
32
33
  editable=True,
33
34
  blank=True,
34
35
  null=True,
35
- related_name="%(app_label)s_%(class)s_source_set",
36
- verbose_name=format_lazy("{} {}", source_label, _("(type)")),
36
+ related_name="%(app_label)s_%(class)s_target_set",
37
+ verbose_name=format_lazy("{} {}", target_label, _("(type)")),
37
38
  )
38
39
 
39
- source_id = GenericForeignKeyIdField(
40
- source_type,
40
+ target_id = GenericForeignKeyIdField(
41
+ target_type,
41
42
  editable=True,
42
43
  blank=True,
43
44
  null=True,
44
- verbose_name=format_lazy("{} {}", source_label, _("(object)")),
45
+ verbose_name=format_lazy("{} {}", target_label, _("(object)")),
45
46
  )
46
47
 
47
- source = GenericForeignKey("source_type", "source_id", verbose_name=source_label)
48
+ target = GenericForeignKey("target_type", "target_id", verbose_name=target_label)
48
49
 
50
+ @classmethod
51
+ def get_simple_parameters(cls):
52
+ for p in super().get_simple_parameters():
53
+ yield p
54
+ yield "target_type"
55
+ yield "target_id"
56
+
57
+ def as_summary_item(self, ar, text=None, **kwargs):
58
+ # raise Exception("20240613")
59
+ if ar is None:
60
+ obj = super()
61
+ elif ar.is_obvious_field('target'):
62
+ obj = self.owner
63
+ elif ar.is_obvious_field('owner'):
64
+ obj = self.target
65
+ else:
66
+ obj = super()
67
+ return obj.as_summary_item(ar, text, **kwargs)
68
+
69
+ dd.update_field(Mention, 'owner', verbose_name=_("Referrer"))
49
70
 
50
71
  class Mentions(dd.Table):
51
72
  required_roles = dd.login_required(SiteStaff)
52
73
  editable = False
53
74
  model = "memo.Mention"
54
- column_names = "source owner *"
75
+ column_names = "owner target *"
55
76
  # detail_layout = """
56
77
  # id comment owner created
57
78
  # """
58
79
 
80
+ # Not used because when you are on the owner, you can see the mentions in the memo text
81
+ # class MentionsByOwner(Mentions):
82
+ # label = _("Mentions")
83
+ # master_key = "owner"
84
+ # column_names = "target *"
85
+ # default_display_modes = {None: constants.DISPLAY_MODE_SUMMARY}
59
86
 
60
- class MentionsByOwner(Mentions):
61
- master_key = "owner"
62
- column_names = "source *"
87
+ class MentionsByTarget(Mentions):
88
+ label = _("Mentioned by")
89
+ master_key = "target"
90
+ column_names = "owner *"
91
+ default_display_modes = {None: constants.DISPLAY_MODE_SUMMARY}