viur-core 3.8.0.dev4__tar.gz → 3.8.0.dev6__tar.gz

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 (125) hide show
  1. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/PKG-INFO +2 -1
  2. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/pyproject.toml +1 -0
  3. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/__init__.py +14 -5
  4. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/__init__.py +2 -0
  5. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/base.py +1 -1
  6. viur_core-3.8.0.dev6/src/viur/core/bones/image.py +36 -0
  7. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/uid.py +1 -1
  8. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/config.py +11 -0
  9. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/modules/file.py +18 -10
  10. viur_core-3.8.0.dev6/src/viur/core/modules/history.py +604 -0
  11. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/prototypes/singleton.py +10 -4
  12. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/prototypes/tree.py +8 -2
  13. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/request.py +23 -11
  14. viur_core-3.8.0.dev6/src/viur/core/skeleton/__init__.py +53 -0
  15. viur_core-3.8.0.dev6/src/viur/core/skeleton/adapter.py +144 -0
  16. viur_core-3.8.0.dev6/src/viur/core/skeleton/instance.py +329 -0
  17. viur_core-3.8.0.dev6/src/viur/core/skeleton/meta.py +448 -0
  18. viur_core-3.8.0.dev6/src/viur/core/skeleton/relskel.py +85 -0
  19. viur_core-3.8.0.dev6/src/viur/core/skeleton/skeleton.py +832 -0
  20. viur_core-3.8.0.dev6/src/viur/core/skeleton/tasks.py +264 -0
  21. viur_core-3.8.0.dev6/src/viur/core/skeleton/utils.py +59 -0
  22. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/tasks.py +1 -1
  23. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/version.py +1 -1
  24. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur_core.egg-info/PKG-INFO +2 -1
  25. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur_core.egg-info/SOURCES.txt +10 -1
  26. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur_core.egg-info/requires.txt +1 -0
  27. viur_core-3.8.0.dev4/src/viur/core/skeleton.py +0 -2139
  28. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/LICENSE +0 -0
  29. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/README.md +0 -0
  30. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/setup.cfg +0 -0
  31. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/boolean.py +0 -0
  32. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/captcha.py +0 -0
  33. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/color.py +0 -0
  34. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/credential.py +0 -0
  35. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/date.py +0 -0
  36. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/email.py +0 -0
  37. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/file.py +0 -0
  38. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/json.py +0 -0
  39. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/key.py +0 -0
  40. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/numeric.py +0 -0
  41. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/password.py +0 -0
  42. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/phone.py +0 -0
  43. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/randomslice.py +0 -0
  44. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/raw.py +0 -0
  45. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/record.py +0 -0
  46. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/relational.py +0 -0
  47. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/select.py +0 -0
  48. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/selectcountry.py +0 -0
  49. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/sortindex.py +0 -0
  50. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/spam.py +0 -0
  51. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/spatial.py +0 -0
  52. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/string.py +0 -0
  53. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/text.py +0 -0
  54. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/treeleaf.py +0 -0
  55. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/treenode.py +0 -0
  56. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/uri.py +0 -0
  57. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/bones/user.py +0 -0
  58. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/cache.py +0 -0
  59. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/current.py +0 -0
  60. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/db/__init__.py +0 -0
  61. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/db/cache.py +0 -0
  62. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/db/config.py +0 -0
  63. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/db/overrides.py +0 -0
  64. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/db/query.py +0 -0
  65. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/db/transport.py +0 -0
  66. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/db/types.py +0 -0
  67. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/db/utils.py +0 -0
  68. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/decorators.py +0 -0
  69. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/email.py +0 -0
  70. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/errors.py +0 -0
  71. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/i18n.py +0 -0
  72. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/languages/__init__.py +0 -0
  73. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/languages/de.py +0 -0
  74. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/languages/en.py +0 -0
  75. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/logging.py +0 -0
  76. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/module.py +0 -0
  77. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/modules/__init__.py +0 -0
  78. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/modules/formmailer.py +0 -0
  79. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/modules/moduleconf.py +0 -0
  80. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/modules/page.py +0 -0
  81. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/modules/script.py +0 -0
  82. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/modules/site.py +0 -0
  83. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/modules/translation.py +0 -0
  84. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/modules/user.py +0 -0
  85. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/pagination.py +0 -0
  86. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/prototypes/__init__.py +0 -0
  87. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/prototypes/instanced_module.py +0 -0
  88. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/prototypes/list.py +0 -0
  89. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/prototypes/skelmodule.py +0 -0
  90. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/ratelimit.py +0 -0
  91. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/__init__.py +0 -0
  92. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/abstract.py +0 -0
  93. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/__init__.py +0 -0
  94. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/default.py +0 -0
  95. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/env/__init__.py +0 -0
  96. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/env/date.py +0 -0
  97. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/env/debug.py +0 -0
  98. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/env/regex.py +0 -0
  99. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/env/session.py +0 -0
  100. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/env/strings.py +0 -0
  101. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/env/tests.py +0 -0
  102. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/env/viur.py +0 -0
  103. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/user.py +0 -0
  104. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/html/utils.py +0 -0
  105. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/json/__init__.py +0 -0
  106. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/json/default.py +0 -0
  107. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/json/user.py +0 -0
  108. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/vi/__init__.py +0 -0
  109. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/render/vi/user.py +0 -0
  110. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/scripts/viur_migrate.py +0 -0
  111. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/secret.py +0 -0
  112. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/securityheaders.py +0 -0
  113. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/securitykey.py +0 -0
  114. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/session.py +0 -0
  115. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/template/error.html +0 -0
  116. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/template/vi_user_google_login.html +0 -0
  117. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/utils/__init__.py +0 -0
  118. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/utils/json.py +0 -0
  119. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/utils/parse.py +0 -0
  120. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur/core/utils/string.py +0 -0
  121. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur_core.egg-info/dependency_links.txt +0 -0
  122. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur_core.egg-info/entry_points.txt +0 -0
  123. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/src/viur_core.egg-info/top_level.txt +0 -0
  124. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/tests/test_config.py +0 -0
  125. {viur_core-3.8.0.dev4 → viur_core-3.8.0.dev6}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: viur-core
3
- Version: 3.8.0.dev4
3
+ Version: 3.8.0.dev6
4
4
  Summary: The core component of ViUR, a development framework for Google App Engine
5
5
  Author-email: Mausbrand Informationssysteme GmbH <devs@viur.dev>
6
6
  Maintainer-email: Jan Max Meyer <jm@mausbrand.de>
@@ -45,6 +45,7 @@ Requires-Dist: appengine-python-standard~=1.0
45
45
  Requires-Dist: Deprecated~=1.2
46
46
  Requires-Dist: google-api-core[grpc]~=2.0
47
47
  Requires-Dist: google-auth~=2.0
48
+ Requires-Dist: google-cloud-bigquery~=3.0
48
49
  Requires-Dist: google-cloud-datastore~=2.0
49
50
  Requires-Dist: google-cloud-iam~=2.0
50
51
  Requires-Dist: google-cloud-logging~=3.0
@@ -10,6 +10,7 @@ dependencies = [
10
10
  "Deprecated~=1.2",
11
11
  "google-api-core[grpc]~=2.0",
12
12
  "google-auth~=2.0",
13
+ "google-cloud-bigquery~=3.0",
13
14
  "google-cloud-datastore~=2.0",
14
15
  "google-cloud-iam~=2.0",
15
16
  "google-cloud-logging~=3.0",
@@ -153,11 +153,20 @@ def __build_app(modules: ModuleType | object, renderers: ModuleType | object, de
153
153
  from viur.core.modules.script import Script # noqa: E402 # import works only here because circular imports
154
154
  from viur.core.modules.translation import Translation # noqa: E402 # import works only here because circular imports
155
155
  from viur.core.prototypes.instanced_module import InstancedModule # noqa: E402 # import works only here because circular imports
156
-
157
- modules._tasks = TaskHandler
158
- modules._moduleconf = ModuleConf
159
- modules._translation = Translation
160
- modules.script = Script
156
+ from viur.core.modules.history import History # noqa: E402 # import works only here because circular imports
157
+
158
+ for name, cls in {
159
+ "_tasks": TaskHandler,
160
+ "_moduleconf": ModuleConf,
161
+ "_translation": Translation,
162
+ "_history": History,
163
+ "script": Script,
164
+ }.items():
165
+ # Check whether name is contained in modules so that it can be overwritten
166
+ if name not in vars(modules):
167
+ setattr(modules, name, cls)
168
+
169
+ assert issubclass(getattr(modules, name), cls)
161
170
 
162
171
  # Resolver defines the URL mapping
163
172
  resolver = {}
@@ -19,6 +19,7 @@ from .credential import CredentialBone
19
19
  from .date import DateBone
20
20
  from .email import EmailBone
21
21
  from .file import FileBone
22
+ from .image import ImageBone
22
23
  from .json import JsonBone
23
24
  from .key import KeyBone
24
25
  from .numeric import NumericBone
@@ -60,6 +61,7 @@ __all = [
60
61
  "DateBone",
61
62
  "EmailBone",
62
63
  "FileBone",
64
+ "ImageBone",
63
65
  "JsonBone",
64
66
  "KeyBone",
65
67
  "MultipleConstraints",
@@ -1070,7 +1070,7 @@ class BaseBone(object):
1070
1070
  db_obj[name] = value
1071
1071
  db.put(db_obj)
1072
1072
 
1073
- if db.IsInTransaction():
1073
+ if db.is_in_transaction():
1074
1074
  transact()
1075
1075
  else:
1076
1076
  db.run_in_transaction(transact)
@@ -0,0 +1,36 @@
1
+ import typing as t
2
+ from .. import i18n
3
+ from .file import FileBone
4
+ from .string import StringBone
5
+ from ..skeleton.relskel import RelSkel
6
+ from ..config import conf
7
+
8
+
9
+ class ImageBoneRelSkel(RelSkel):
10
+ alt = StringBone(
11
+ descr=i18n.translate(
12
+ "viur.core.image.alt",
13
+ defaultText="Alternative description",
14
+ ),
15
+ searchable=True,
16
+ languages=conf.i18n.available_languages,
17
+ )
18
+
19
+
20
+ class ImageBone(FileBone):
21
+ type = FileBone.type + ".image"
22
+
23
+ def __init__(
24
+ self,
25
+ *,
26
+ public: bool = True,
27
+ using: t.Optional[RelSkel] = ImageBoneRelSkel,
28
+ validMimeTypes: None | t.Iterable[str] = ["image/*"],
29
+ **kwargs,
30
+ ):
31
+ super().__init__(
32
+ public=public,
33
+ using=using,
34
+ validMimeTypes=validMimeTypes,
35
+ **kwargs,
36
+ )
@@ -25,7 +25,7 @@ def generate_number(db_key: db.Key) -> int:
25
25
  raise ValueError("Can't set the Uid")
26
26
  return db_obj["count"]
27
27
 
28
- if db.IsInTransaction():
28
+ if db.is_in_transaction():
29
29
  return transact(db_key)
30
30
  else:
31
31
  return db.run_in_transaction(transact, db_key)
@@ -577,6 +577,15 @@ class Email(ConfigType):
577
577
  }
578
578
 
579
579
 
580
+ class History(ConfigType):
581
+ databases: Multiple[str] = ["viur"]
582
+ """All history related settings."""
583
+ excluded_actions: Multiple[str] = []
584
+ """List of all action that are should not be logged."""
585
+ excluded_kinds: Multiple[str] = []
586
+ """List of all kinds that should be logged."""
587
+
588
+
580
589
  class I18N(ConfigType):
581
590
  """All i18n, multilang related settings."""
582
591
 
@@ -910,6 +919,7 @@ class Conf(ConfigType):
910
919
  skeleton_search_path: Multiple[str] = [
911
920
  "/skeletons/", # skeletons of the project
912
921
  "/viur/core/", # system-defined skeletons of viur-core
922
+ "/viur/src/viur/core/", # fixme: test suite
913
923
  "/viur-core/core/" # system-defined skeletons of viur-core, only used by editable installation
914
924
  ]
915
925
  """Priority, in which skeletons are loaded"""
@@ -984,6 +994,7 @@ class Conf(ConfigType):
984
994
  self.i18n = I18N(parent=self)
985
995
  self.user = User(parent=self)
986
996
  self.instance = Instance(parent=self)
997
+ self.history = History(parent=self)
987
998
 
988
999
  _mapping = {
989
1000
  # debug
@@ -23,10 +23,9 @@ from google.appengine.api import blobstore, images
23
23
  from google.cloud import storage
24
24
  from google.oauth2.service_account import Credentials as ServiceAccountCredentials
25
25
 
26
- from viur.core import conf, current, db, errors, utils
26
+ from viur.core import conf, current, db, errors, utils, i18n
27
27
  from viur.core.bones import BaseBone, BooleanBone, KeyBone, NumericBone, StringBone
28
28
  from viur.core.decorators import *
29
- from viur.core.i18n import LanguageWrapper
30
29
  from viur.core.prototypes.tree import SkelType, Tree, TreeSkel
31
30
  from viur.core.skeleton import SkeletonInstance, skeletonByKind
32
31
  from viur.core.tasks import CallDeferred, DeleteEntitiesIter, PeriodicTask
@@ -303,6 +302,22 @@ class FileLeafSkel(TreeSkel):
303
302
  """
304
303
  kindName = "file"
305
304
 
305
+ name = StringBone(
306
+ descr="Filename",
307
+ caseSensitive=False,
308
+ searchable=True,
309
+ vfunc=lambda val: None if File.is_valid_filename(val) else "Invalid filename provided",
310
+ )
311
+
312
+ alt = StringBone(
313
+ descr=i18n.translate(
314
+ "viur.core.image.alt",
315
+ defaultText="Alternative description",
316
+ ),
317
+ searchable=True,
318
+ languages=conf.i18n.available_languages,
319
+ )
320
+
306
321
  size = StringBone(
307
322
  descr="Size",
308
323
  readOnly=True,
@@ -314,13 +329,6 @@ class FileLeafSkel(TreeSkel):
314
329
  readOnly=True,
315
330
  )
316
331
 
317
- name = StringBone(
318
- descr="Filename",
319
- caseSensitive=False,
320
- searchable=True,
321
- vfunc=lambda val: None if conf.main_app.file.is_valid_filename(val) else "Invalid filename provided",
322
- )
323
-
324
332
  mimetype = StringBone(
325
333
  descr="MIME-Type",
326
334
  readOnly=True,
@@ -713,7 +721,7 @@ class File(Tree):
713
721
  if not file:
714
722
  return ""
715
723
 
716
- if isinstance(file, LanguageWrapper):
724
+ if isinstance(file, i18n.LanguageWrapper):
717
725
  language = language or current.language.get()
718
726
  if not language or not (file := cls.get(language)):
719
727
  return ""