flask-appbuilder 3.2.1rc1__py3-none-any.whl → 5.0.2rc1__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 (228) hide show
  1. flask_appbuilder/__init__.py +2 -3
  2. flask_appbuilder/_compat.py +0 -1
  3. flask_appbuilder/actions.py +14 -14
  4. flask_appbuilder/api/__init__.py +741 -527
  5. flask_appbuilder/api/convert.py +104 -98
  6. flask_appbuilder/api/manager.py +14 -8
  7. flask_appbuilder/api/schemas.py +12 -1
  8. flask_appbuilder/babel/manager.py +12 -16
  9. flask_appbuilder/base.py +353 -280
  10. flask_appbuilder/basemanager.py +1 -1
  11. flask_appbuilder/baseviews.py +241 -164
  12. flask_appbuilder/charts/jsontools.py +10 -10
  13. flask_appbuilder/charts/views.py +56 -60
  14. flask_appbuilder/cli.py +115 -70
  15. flask_appbuilder/const.py +52 -52
  16. flask_appbuilder/exceptions.py +67 -5
  17. flask_appbuilder/fields.py +32 -23
  18. flask_appbuilder/fieldwidgets.py +34 -27
  19. flask_appbuilder/filemanager.py +33 -45
  20. flask_appbuilder/filters.py +11 -13
  21. flask_appbuilder/forms.py +31 -35
  22. flask_appbuilder/hooks.py +90 -0
  23. flask_appbuilder/menu.py +35 -10
  24. flask_appbuilder/models/base.py +47 -57
  25. flask_appbuilder/models/decorators.py +13 -13
  26. flask_appbuilder/models/filters.py +42 -38
  27. flask_appbuilder/models/generic/__init__.py +29 -29
  28. flask_appbuilder/models/generic/filters.py +11 -3
  29. flask_appbuilder/models/generic/interface.py +1 -3
  30. flask_appbuilder/models/group.py +37 -39
  31. flask_appbuilder/models/mixins.py +22 -18
  32. flask_appbuilder/models/sqla/__init__.py +19 -72
  33. flask_appbuilder/models/sqla/base.py +24 -0
  34. flask_appbuilder/models/sqla/base_legacy.py +132 -0
  35. flask_appbuilder/models/sqla/filters.py +132 -19
  36. flask_appbuilder/models/sqla/interface.py +390 -276
  37. flask_appbuilder/security/api.py +31 -35
  38. flask_appbuilder/security/decorators.py +181 -83
  39. flask_appbuilder/security/forms.py +20 -31
  40. flask_appbuilder/security/manager.py +715 -489
  41. flask_appbuilder/security/registerviews.py +29 -112
  42. flask_appbuilder/security/schemas.py +43 -0
  43. flask_appbuilder/security/sqla/apis/__init__.py +8 -0
  44. flask_appbuilder/security/sqla/apis/group/__init__.py +1 -0
  45. flask_appbuilder/security/sqla/apis/group/api.py +227 -0
  46. flask_appbuilder/security/sqla/apis/group/schema.py +73 -0
  47. flask_appbuilder/security/sqla/apis/permission/__init__.py +1 -0
  48. flask_appbuilder/security/sqla/apis/permission/api.py +19 -0
  49. flask_appbuilder/security/sqla/apis/permission_view_menu/__init__.py +1 -0
  50. flask_appbuilder/security/sqla/apis/permission_view_menu/api.py +16 -0
  51. flask_appbuilder/security/sqla/apis/role/__init__.py +1 -0
  52. flask_appbuilder/security/sqla/apis/role/api.py +306 -0
  53. flask_appbuilder/security/sqla/apis/role/schema.py +27 -0
  54. flask_appbuilder/security/sqla/apis/user/__init__.py +1 -0
  55. flask_appbuilder/security/sqla/apis/user/api.py +292 -0
  56. flask_appbuilder/security/sqla/apis/user/schema.py +97 -0
  57. flask_appbuilder/security/sqla/apis/user/validator.py +27 -0
  58. flask_appbuilder/security/sqla/apis/view_menu/__init__.py +1 -0
  59. flask_appbuilder/security/sqla/apis/view_menu/api.py +18 -0
  60. flask_appbuilder/security/sqla/manager.py +421 -203
  61. flask_appbuilder/security/sqla/models.py +192 -57
  62. flask_appbuilder/security/utils.py +9 -0
  63. flask_appbuilder/security/views.py +232 -229
  64. flask_appbuilder/static/.DS_Store +0 -0
  65. flask_appbuilder/static/appbuilder/css/ab.css +20 -12
  66. flask_appbuilder/static/appbuilder/css/bootstrap-datepicker/bootstrap-datepicker3.min.css +7 -0
  67. flask_appbuilder/static/appbuilder/css/bootstrap.min.css.map +1 -0
  68. flask_appbuilder/static/appbuilder/css/flags/flags16.css +249 -245
  69. flask_appbuilder/static/appbuilder/css/fontawesome/all.min.css +6 -0
  70. flask_appbuilder/static/appbuilder/css/fontawesome/brands.min.css +6 -0
  71. flask_appbuilder/static/appbuilder/css/fontawesome/fontawesome.min.css +6 -0
  72. flask_appbuilder/static/appbuilder/css/fontawesome/regular.min.css +6 -0
  73. flask_appbuilder/static/appbuilder/css/fontawesome/solid.min.css +6 -0
  74. flask_appbuilder/static/appbuilder/css/fontawesome/svg-with-js.min.css +6 -0
  75. flask_appbuilder/static/appbuilder/css/fontawesome/v4-font-face.min.css +6 -0
  76. flask_appbuilder/static/appbuilder/css/fontawesome/v4-shims.min.css +6 -0
  77. flask_appbuilder/static/appbuilder/css/fontawesome/v5-font-face.min.css +6 -0
  78. flask_appbuilder/static/appbuilder/css/images/flags16.png +0 -0
  79. flask_appbuilder/static/appbuilder/css/select2/select2-bootstrap.min.css +7 -0
  80. flask_appbuilder/static/appbuilder/css/select2/select2.min.css +1 -0
  81. flask_appbuilder/static/appbuilder/css/swagger/swagger-ui.css +3 -0
  82. flask_appbuilder/static/appbuilder/css/webfonts/fa-brands-400.ttf +0 -0
  83. flask_appbuilder/static/appbuilder/css/webfonts/fa-brands-400.woff2 +0 -0
  84. flask_appbuilder/static/appbuilder/css/webfonts/fa-regular-400.ttf +0 -0
  85. flask_appbuilder/static/appbuilder/css/webfonts/fa-regular-400.woff2 +0 -0
  86. flask_appbuilder/static/appbuilder/css/webfonts/fa-solid-900.ttf +0 -0
  87. flask_appbuilder/static/appbuilder/css/webfonts/fa-solid-900.woff2 +0 -0
  88. flask_appbuilder/static/appbuilder/css/webfonts/fa-v4compatibility.ttf +0 -0
  89. flask_appbuilder/static/appbuilder/css/webfonts/fa-v4compatibility.woff2 +0 -0
  90. flask_appbuilder/static/appbuilder/js/ab.js +33 -23
  91. flask_appbuilder/static/appbuilder/js/ab_filters.js +91 -84
  92. flask_appbuilder/static/appbuilder/js/bootstrap-datepicker/bootstrap-datepicker.min.js +8 -0
  93. flask_appbuilder/static/appbuilder/js/jquery-latest.js +2 -2
  94. flask_appbuilder/static/appbuilder/js/select2/select2.min.js +2 -0
  95. flask_appbuilder/static/appbuilder/js/swagger-ui-bundle.js +3 -0
  96. flask_appbuilder/templates/appbuilder/baselib.html +9 -3
  97. flask_appbuilder/templates/appbuilder/general/lib.html +60 -34
  98. flask_appbuilder/templates/appbuilder/general/model/edit.html +1 -1
  99. flask_appbuilder/templates/appbuilder/general/model/edit_cascade.html +1 -1
  100. flask_appbuilder/templates/appbuilder/general/model/search.html +3 -2
  101. flask_appbuilder/templates/appbuilder/general/model/show.html +1 -1
  102. flask_appbuilder/templates/appbuilder/general/model/show_cascade.html +1 -1
  103. flask_appbuilder/templates/appbuilder/general/security/login_db.html +7 -7
  104. flask_appbuilder/templates/appbuilder/general/security/login_ldap.html +5 -5
  105. flask_appbuilder/templates/appbuilder/general/security/login_oauth.html +24 -49
  106. flask_appbuilder/templates/appbuilder/general/widgets/base_list.html +2 -1
  107. flask_appbuilder/templates/appbuilder/general/widgets/chart.html +4 -2
  108. flask_appbuilder/templates/appbuilder/general/widgets/direct_chart.html +4 -3
  109. flask_appbuilder/templates/appbuilder/general/widgets/multiple_chart.html +3 -2
  110. flask_appbuilder/templates/appbuilder/general/widgets/search.html +11 -10
  111. flask_appbuilder/templates/appbuilder/init.html +37 -43
  112. flask_appbuilder/templates/appbuilder/navbar_menu.html +1 -1
  113. flask_appbuilder/templates/appbuilder/navbar_right.html +2 -2
  114. flask_appbuilder/templates/appbuilder/swagger/swagger.html +22 -19
  115. flask_appbuilder/translations/de/LC_MESSAGES/messages.mo +0 -0
  116. flask_appbuilder/translations/de/LC_MESSAGES/messages.po +305 -161
  117. flask_appbuilder/translations/fa/LC_MESSAGES/messages.mo +0 -0
  118. flask_appbuilder/translations/fa/LC_MESSAGES/messages.po +802 -0
  119. flask_appbuilder/translations/fr/LC_MESSAGES/messages.po +461 -319
  120. flask_appbuilder/translations/pt_BR/LC_MESSAGES/messages.po +650 -650
  121. flask_appbuilder/translations/ru/LC_MESSAGES/messages.po +1 -1
  122. flask_appbuilder/translations/sl/LC_MESSAGES/messages.mo +0 -0
  123. flask_appbuilder/translations/sl/LC_MESSAGES/messages.po +690 -0
  124. flask_appbuilder/translations/tr/LC_MESSAGES/messages.mo +0 -0
  125. flask_appbuilder/translations/tr/LC_MESSAGES/messages.po +1015 -0
  126. flask_appbuilder/upload.py +20 -22
  127. flask_appbuilder/urltools.py +39 -19
  128. flask_appbuilder/utils/base.py +76 -0
  129. flask_appbuilder/utils/legacy.py +33 -0
  130. flask_appbuilder/utils/limit.py +20 -0
  131. flask_appbuilder/validators.py +73 -14
  132. flask_appbuilder/views.py +75 -424
  133. flask_appbuilder/widgets.py +50 -51
  134. {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2rc1.dist-info}/METADATA +36 -76
  135. flask_appbuilder-5.0.2rc1.dist-info/RECORD +240 -0
  136. {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2rc1.dist-info}/WHEEL +1 -1
  137. flask_appbuilder-5.0.2rc1.dist-info/entry_points.txt +2 -0
  138. Flask_AppBuilder-3.2.1rc1.dist-info/RECORD +0 -270
  139. Flask_AppBuilder-3.2.1rc1.dist-info/entry_points.txt +0 -6
  140. flask_appbuilder/console.py +0 -426
  141. flask_appbuilder/models/mongoengine/__init__.py +0 -0
  142. flask_appbuilder/models/mongoengine/fields.py +0 -65
  143. flask_appbuilder/models/mongoengine/filters.py +0 -145
  144. flask_appbuilder/models/mongoengine/interface.py +0 -328
  145. flask_appbuilder/security/mongoengine/__init__.py +0 -0
  146. flask_appbuilder/security/mongoengine/manager.py +0 -402
  147. flask_appbuilder/security/mongoengine/models.py +0 -120
  148. flask_appbuilder/static/appbuilder/css/font-awesome.min.css +0 -4
  149. flask_appbuilder/static/appbuilder/datepicker/bootstrap-datepicker.css +0 -9
  150. flask_appbuilder/static/appbuilder/datepicker/bootstrap-datepicker.js +0 -28
  151. flask_appbuilder/static/appbuilder/fonts/FontAwesome.otf +0 -0
  152. flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.eot +0 -0
  153. flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.svg +0 -2671
  154. flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.ttf +0 -0
  155. flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.woff +0 -0
  156. flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.woff2 +0 -0
  157. flask_appbuilder/static/appbuilder/img/aol.png +0 -0
  158. flask_appbuilder/static/appbuilder/img/flags/flags16.png +0 -0
  159. flask_appbuilder/static/appbuilder/img/flickr.png +0 -0
  160. flask_appbuilder/static/appbuilder/img/google.png +0 -0
  161. flask_appbuilder/static/appbuilder/img/myopenid.png +0 -0
  162. flask_appbuilder/static/appbuilder/img/yahoo.png +0 -0
  163. flask_appbuilder/static/appbuilder/js/_google_charts.js +0 -39
  164. flask_appbuilder/static/appbuilder/js/html5shiv.js +0 -8
  165. flask_appbuilder/static/appbuilder/js/respond.min.js +0 -6
  166. flask_appbuilder/static/appbuilder/select2/select2-spinner.gif +0 -0
  167. flask_appbuilder/static/appbuilder/select2/select2.css +0 -1205
  168. flask_appbuilder/static/appbuilder/select2/select2.js +0 -23
  169. flask_appbuilder/static/appbuilder/select2/select2.png +0 -0
  170. flask_appbuilder/static/appbuilder/select2/select2x2.png +0 -0
  171. flask_appbuilder/templates/appbuilder/general/security/login_oid.html +0 -129
  172. flask_appbuilder/templates/appbuilder/general/security/resetpassword.html +0 -29
  173. flask_appbuilder/tests/__init__.py +0 -0
  174. flask_appbuilder/tests/__pycache__/__init__.cpython-36.pyc +0 -0
  175. flask_appbuilder/tests/__pycache__/__init__.cpython-37.pyc +0 -0
  176. flask_appbuilder/tests/__pycache__/_test_auth_ldap.cpython-37.pyc +0 -0
  177. flask_appbuilder/tests/__pycache__/_test_auth_oauth.cpython-37.pyc +0 -0
  178. flask_appbuilder/tests/__pycache__/_test_ldapsearch.cpython-36.pyc +0 -0
  179. flask_appbuilder/tests/__pycache__/_test_oauth_registration_role.cpython-36.pyc +0 -0
  180. flask_appbuilder/tests/__pycache__/base.cpython-36.pyc +0 -0
  181. flask_appbuilder/tests/__pycache__/base.cpython-37.pyc +0 -0
  182. flask_appbuilder/tests/__pycache__/config_api.cpython-36.pyc +0 -0
  183. flask_appbuilder/tests/__pycache__/config_api.cpython-37.pyc +0 -0
  184. flask_appbuilder/tests/__pycache__/const.cpython-36.pyc +0 -0
  185. flask_appbuilder/tests/__pycache__/const.cpython-37.pyc +0 -0
  186. flask_appbuilder/tests/__pycache__/test_0_fixture.cpython-36.pyc +0 -0
  187. flask_appbuilder/tests/__pycache__/test_0_fixture.cpython-37.pyc +0 -0
  188. flask_appbuilder/tests/__pycache__/test_api.cpython-36.pyc +0 -0
  189. flask_appbuilder/tests/__pycache__/test_api.cpython-37.pyc +0 -0
  190. flask_appbuilder/tests/__pycache__/test_fab_cli.cpython-36.pyc +0 -0
  191. flask_appbuilder/tests/__pycache__/test_fab_cli.cpython-37.pyc +0 -0
  192. flask_appbuilder/tests/__pycache__/test_menu.cpython-36.pyc +0 -0
  193. flask_appbuilder/tests/__pycache__/test_menu.cpython-37.pyc +0 -0
  194. flask_appbuilder/tests/__pycache__/test_mongoengine.cpython-36.pyc +0 -0
  195. flask_appbuilder/tests/__pycache__/test_mvc.cpython-36.pyc +0 -0
  196. flask_appbuilder/tests/__pycache__/test_mvc.cpython-37.pyc +0 -0
  197. flask_appbuilder/tests/__pycache__/test_sqlalchemy.cpython-36.pyc +0 -0
  198. flask_appbuilder/tests/__pycache__/test_sqlalchemy.cpython-37.pyc +0 -0
  199. flask_appbuilder/tests/_test_auth_ldap.py +0 -1045
  200. flask_appbuilder/tests/_test_auth_oauth.py +0 -419
  201. flask_appbuilder/tests/_test_ldapsearch.py +0 -135
  202. flask_appbuilder/tests/_test_oauth_registration_role.py +0 -59
  203. flask_appbuilder/tests/app.db +0 -0
  204. flask_appbuilder/tests/base.py +0 -90
  205. flask_appbuilder/tests/config_api.py +0 -21
  206. flask_appbuilder/tests/const.py +0 -9
  207. flask_appbuilder/tests/mongoengine/__init__.py +0 -0
  208. flask_appbuilder/tests/mongoengine/__pycache__/__init__.cpython-36.pyc +0 -0
  209. flask_appbuilder/tests/mongoengine/__pycache__/__init__.cpython-37.pyc +0 -0
  210. flask_appbuilder/tests/mongoengine/__pycache__/models.cpython-36.pyc +0 -0
  211. flask_appbuilder/tests/mongoengine/models.py +0 -41
  212. flask_appbuilder/tests/sqla/__init__.py +0 -0
  213. flask_appbuilder/tests/sqla/__pycache__/__init__.cpython-36.pyc +0 -0
  214. flask_appbuilder/tests/sqla/__pycache__/__init__.cpython-37.pyc +0 -0
  215. flask_appbuilder/tests/sqla/__pycache__/models.cpython-36.pyc +0 -0
  216. flask_appbuilder/tests/sqla/__pycache__/models.cpython-37.pyc +0 -0
  217. flask_appbuilder/tests/sqla/models.py +0 -340
  218. flask_appbuilder/tests/test_0_fixture.py +0 -39
  219. flask_appbuilder/tests/test_api.py +0 -2790
  220. flask_appbuilder/tests/test_fab_cli.py +0 -72
  221. flask_appbuilder/tests/test_menu.py +0 -122
  222. flask_appbuilder/tests/test_mongoengine.py +0 -572
  223. flask_appbuilder/tests/test_mvc.py +0 -1710
  224. flask_appbuilder/tests/test_sqlalchemy.py +0 -24
  225. flask_appbuilder/translations/__pycache__/__init__.cpython-36.pyc +0 -0
  226. flask_appbuilder/translations/es/LC_MESSAGES/messages.po~ +0 -582
  227. {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2rc1.dist-info}/LICENSE +0 -0
  228. {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2rc1.dist-info}/top_level.txt +0 -0
@@ -3,9 +3,7 @@ from functools import reduce
3
3
  import logging
4
4
  from typing import Any, Type
5
5
 
6
- from flask_babel import lazy_gettext
7
-
8
- from .filters import BaseFilterConverter, Filters
6
+ from flask_appbuilder.models.filters import BaseFilterConverter, Filters
9
7
 
10
8
  try:
11
9
  import enum
@@ -17,36 +15,25 @@ except ImportError:
17
15
  log = logging.getLogger(__name__)
18
16
 
19
17
 
20
- class BaseInterface(object):
18
+ class BaseInterface:
21
19
  """
22
- Base class for all data model interfaces.
23
- Sub class it to implement your own interface for some data engine.
20
+ Base class for all data model interfaces.
21
+ Sub class it to implement your own interface for some data engine.
24
22
  """
25
23
 
26
24
  filter_converter_class = Type[BaseFilterConverter]
27
25
  """ when sub classing override with your own custom filter converter """
28
26
 
29
- """ Messages to display on CRUD Events """
30
- add_row_message = lazy_gettext("Added Row")
31
- edit_row_message = lazy_gettext("Changed Row")
32
- delete_row_message = lazy_gettext("Deleted Row")
33
- delete_integrity_error_message = lazy_gettext(
34
- "Associated data exists, please delete them first"
35
- )
36
- add_integrity_error_message = lazy_gettext(
37
- "Integrity error, probably unique constraint"
38
- )
39
- edit_integrity_error_message = lazy_gettext(
40
- "Integrity error, probably unique constraint"
41
- )
42
- general_error_message = lazy_gettext("General Error")
43
-
44
- """ Tuple with message and text with severity type ex: ("Added Row", "info") """
45
- message = ()
46
-
47
27
  def __init__(self, obj: Type[Any]):
48
28
  self.obj = obj
49
29
 
30
+ # def __getattr__(self, name: str) -> Any:
31
+ # """
32
+ # Make mypy happy about the injected filters like self.datamodel.FilterEqual
33
+ # https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html#when-you-re-puzzled-or-when-things-are-complicated
34
+ # """
35
+ # return super().__getattr__(name)
36
+
50
37
  def _get_attr(self, col_name):
51
38
  if not hasattr(self.obj, col_name):
52
39
  # it's an inner obj attr
@@ -96,13 +83,13 @@ class BaseInterface(object):
96
83
 
97
84
  def _get_values(self, lst, list_columns):
98
85
  """
99
- Get Values: formats values for list template.
100
- returns [{'col_name':'col_value',....},{'col_name':'col_value',....}]
86
+ Get Values: formats values for list template.
87
+ returns [{'col_name':'col_value',....},{'col_name':'col_value',....}]
101
88
 
102
- :param lst:
103
- The list of item objects from query
104
- :param list_columns:
105
- The list of columns to include
89
+ :param lst:
90
+ The list of item objects from query
91
+ :param list_columns:
92
+ The list of columns to include
106
93
  """
107
94
  retlst = []
108
95
  for item in lst:
@@ -114,13 +101,13 @@ class BaseInterface(object):
114
101
 
115
102
  def get_values(self, lst, list_columns):
116
103
  """
117
- Get Values: formats values for list template.
118
- returns [{'col_name':'col_value',....},{'col_name':'col_value',....}]
104
+ Get Values: formats values for list template.
105
+ returns [{'col_name':'col_value',....},{'col_name':'col_value',....}]
119
106
 
120
- :param lst:
121
- The list of item objects from query
122
- :param list_columns:
123
- The list of columns to include
107
+ :param lst:
108
+ The list of item objects from query
109
+ :param list_columns:
110
+ The list of columns to include
124
111
  """
125
112
  for item in lst:
126
113
  retdict = {}
@@ -130,7 +117,7 @@ class BaseInterface(object):
130
117
 
131
118
  def get_values_json(self, lst, list_columns):
132
119
  """
133
- Converts list of objects from query to JSON
120
+ Converts list of objects from query to JSON
134
121
  """
135
122
  result = []
136
123
  for item in self.get_values(lst, list_columns):
@@ -210,6 +197,9 @@ class BaseInterface(object):
210
197
  def is_enum(self, col_name):
211
198
  return False
212
199
 
200
+ def is_json(self, col_name):
201
+ return False
202
+
213
203
  def is_relation(self, prop):
214
204
  return False
215
205
 
@@ -238,7 +228,7 @@ class BaseInterface(object):
238
228
  return False
239
229
 
240
230
  def is_pk_composite(self):
241
- raise False
231
+ return False
242
232
 
243
233
  def is_fk(self, col_name):
244
234
  return False
@@ -255,30 +245,30 @@ class BaseInterface(object):
255
245
  -----------------------------------------
256
246
  """
257
247
 
258
- def add(self, item):
248
+ def add(self, item: Any, commit: bool = True) -> None:
259
249
  """
260
- Adds object
250
+ Adds object
261
251
  """
262
252
  raise NotImplementedError
263
253
 
264
- def edit(self, item):
254
+ def edit(self, item: Any, commit: bool = True) -> None:
265
255
  """
266
- Edit (change) object
256
+ Edit (change) object
267
257
  """
268
258
  raise NotImplementedError
269
259
 
270
- def delete(self, item):
260
+ def delete(self, item: Any, commit: bool = True) -> None:
271
261
  """
272
- Deletes object
262
+ Deletes object
273
263
  """
274
264
  raise NotImplementedError
275
265
 
276
- def get_col_default(self, col_name):
266
+ def get_col_default(self, col_name: str):
277
267
  pass
278
268
 
279
269
  def get_keys(self, lst):
280
270
  """
281
- return a list of pk values from object list
271
+ return a list of pk values from object list
282
272
  """
283
273
  pk_name = self.get_pk_name()
284
274
  if self.is_pk_composite():
@@ -288,7 +278,7 @@ class BaseInterface(object):
288
278
 
289
279
  def get_pk_name(self):
290
280
  """
291
- Returns the primary key name
281
+ Returns the primary key name
292
282
  """
293
283
  raise NotImplementedError
294
284
 
@@ -301,8 +291,8 @@ class BaseInterface(object):
301
291
 
302
292
  def get(self, pk, filter=None):
303
293
  """
304
- return the record from key, you can optionally pass filters
305
- if pk exits on the db but filters exclude it it will return none.
294
+ return the record from key, you can optionally pass filters
295
+ if pk exits on the db but filters exclude it it will return none.
306
296
  """
307
297
  pass
308
298
 
@@ -311,11 +301,11 @@ class BaseInterface(object):
311
301
 
312
302
  def get_related_interface(self, col_name):
313
303
  """
314
- Returns a BaseInterface for the related model
315
- of column name.
304
+ Returns a BaseInterface for the related model
305
+ of column name.
316
306
 
317
- :param col_name: Column name with relation
318
- :return: BaseInterface
307
+ :param col_name: Column name with relation
308
+ :return: BaseInterface
319
309
  """
320
310
  raise NotImplementedError
321
311
 
@@ -327,25 +317,25 @@ class BaseInterface(object):
327
317
 
328
318
  def get_columns_list(self):
329
319
  """
330
- Returns a list of all the columns names
320
+ Returns a list of all the columns names
331
321
  """
332
322
  return []
333
323
 
334
324
  def get_user_columns_list(self):
335
325
  """
336
- Returns a list of user viewable columns names
326
+ Returns a list of user viewable columns names
337
327
  """
338
328
  return self.get_columns_list()
339
329
 
340
330
  def get_search_columns_list(self):
341
331
  """
342
- Returns a list of searchable columns names
332
+ Returns a list of searchable columns names
343
333
  """
344
334
  return []
345
335
 
346
336
  def get_order_columns_list(self, list_columns=None):
347
337
  """
348
- Returns a list of order columns names
338
+ Returns a list of order columns names
349
339
  """
350
340
  return []
351
341
 
@@ -1,21 +1,21 @@
1
1
  def renders(col_name):
2
2
  """
3
- Use this decorator to map your custom Model properties to actual
4
- Model db properties. As an example::
3
+ Use this decorator to map your custom Model properties to actual
4
+ Model db properties. As an example::
5
5
 
6
- class MyModel(Model):
7
- id = Column(Integer, primary_key=True)
8
- name = Column(String(50), unique = True, nullable=False)
9
- custom = Column(Integer(20))
6
+ class MyModel(Model):
7
+ id = Column(Integer, primary_key=True)
8
+ name = Column(String(50), unique = True, nullable=False)
9
+ custom = Column(Integer(20))
10
10
 
11
- @renders('custom')
12
- def my_custom(self):
13
- # will render this columns as bold on ListWidget
14
- return Markup('<b>' + custom + '</b>')
11
+ @renders('custom')
12
+ def my_custom(self):
13
+ # will render this columns as bold on ListWidget
14
+ return Markup('<b>' + self.custom + '</b>')
15
15
 
16
- class MyModelView(ModelView):
17
- datamodel = SQLAInterface(MyTable)
18
- list_columns = ['name', 'my_custom']
16
+ class MyModelView(ModelView):
17
+ datamodel = SQLAInterface(MyTable)
18
+ list_columns = ['name', 'my_custom']
19
19
 
20
20
  """
21
21
 
@@ -14,10 +14,10 @@ map_args_filter = {}
14
14
  """ private map for arg_name and child Filter classes """
15
15
 
16
16
 
17
- class BaseFilter(object):
17
+ class BaseFilter:
18
18
  """
19
- Base class for all data filters.
20
- Sub class to implement your own custom filters
19
+ Base class for all data filters.
20
+ Sub class to implement your own custom filters
21
21
  """
22
22
 
23
23
  column_name = ""
@@ -39,14 +39,14 @@ class BaseFilter(object):
39
39
 
40
40
  def __init__(self, column_name, datamodel, is_related_view=False):
41
41
  """
42
- Constructor.
43
-
44
- :param column_name:
45
- Model field name
46
- :param datamodel:
47
- The datamodel access class
48
- :param is_related_view:
49
- Optional internal parameter to filter related views
42
+ Constructor.
43
+
44
+ :param column_name:
45
+ Model field name
46
+ :param datamodel:
47
+ The datamodel access class
48
+ :param is_related_view:
49
+ Optional internal parameter to filter related views
50
50
  """
51
51
  self.column_name = column_name
52
52
  self.datamodel = datamodel
@@ -57,7 +57,7 @@ class BaseFilter(object):
57
57
 
58
58
  def apply(self, query, value):
59
59
  """
60
- Override this to implement your own new filters
60
+ Override this to implement your own new filters
61
61
  """
62
62
  raise NotImplementedError
63
63
 
@@ -67,21 +67,21 @@ class BaseFilter(object):
67
67
 
68
68
  class FilterRelation(BaseFilter):
69
69
  """
70
- Base class for all filters for relations
70
+ Base class for all filters for relations
71
71
  """
72
72
 
73
73
  def apply(self, query, value):
74
74
  """
75
- Override this to implement your own new filters
75
+ Override this to implement your own new filters
76
76
  """
77
77
  raise NotImplementedError
78
78
 
79
79
 
80
80
  class BaseFilterConverter:
81
81
  """
82
- Base Filter Converter, all classes responsible
83
- for the association of columns and possible filters
84
- will inherit from this and override the conversion_table property.
82
+ Base Filter Converter, all classes responsible
83
+ for the association of columns and possible filters
84
+ will inherit from this and override the conversion_table property.
85
85
 
86
86
  """
87
87
 
@@ -114,10 +114,10 @@ class BaseFilterConverter:
114
114
  for conversion in self.conversion_table:
115
115
  if getattr(self.datamodel, conversion[0])(col_name):
116
116
  return [item(col_name, self.datamodel) for item in conversion[1]]
117
- log.warning("Filter type not supported for column: %s" % col_name)
117
+ log.warning("Filter type not supported for column: %s", col_name)
118
118
 
119
119
 
120
- class Filters(object):
120
+ class Filters:
121
121
  filters: List[BaseFilter] = []
122
122
  """ List of instantiated BaseFilter classes """
123
123
  values: List[Any] = []
@@ -135,11 +135,11 @@ class Filters(object):
135
135
  ):
136
136
  """
137
137
 
138
- :param filter_converter: Accepts BaseFilterConverter class
139
- :param search_columns: restricts possible columns,
140
- accepts a list of column names
141
- :param search_filters: Add custom defined filters to specific columns
142
- :param datamodel: Accepts BaseInterface class
138
+ :param filter_converter: Accepts BaseFilterConverter class
139
+ :param search_columns: restricts possible columns,
140
+ accepts a list of column names
141
+ :param search_filters: Add custom defined filters to specific columns
142
+ :param datamodel: Accepts BaseInterface class
143
143
  """
144
144
  self.search_columns = search_columns or []
145
145
  self.filter_converter = filter_converter
@@ -168,9 +168,9 @@ class Filters(object):
168
168
  self.filters = []
169
169
  self.values = []
170
170
 
171
- def _add_filter(self, filter_instance, value):
171
+ def _add_filter(self, filter_instance, values):
172
172
  self.filters.append(filter_instance)
173
- self.values.append(value)
173
+ self.values.append(values)
174
174
 
175
175
  def add_filter_index(
176
176
  self, column_name: str, filter_instance_index: int, value: Any
@@ -226,7 +226,7 @@ class Filters(object):
226
226
  return True
227
227
  return False
228
228
 
229
- def add_filter(self, column_name, filter_class, value):
229
+ def add_filter(self, column_name: str, filter_class: BaseFilter, value: str):
230
230
  self._add_filter(filter_class(column_name, self.datamodel), value)
231
231
  return self
232
232
 
@@ -240,9 +240,9 @@ class Filters(object):
240
240
  self._add_filter(filter_class(column_name, self.datamodel), value)
241
241
  return self
242
242
 
243
- def get_joined_filters(self, filters):
243
+ def get_joined_filters(self, filters) -> "Filters":
244
244
  """
245
- Creates a new filters class with active filters joined
245
+ Creates a new filters class with active filters joined
246
246
  """
247
247
  ret_filters = Filters(self.filter_converter, self.datamodel)
248
248
  ret_filters.filters = self.filters + filters.filters
@@ -251,9 +251,9 @@ class Filters(object):
251
251
 
252
252
  def copy(self):
253
253
  """
254
- Returns a copy of this object
254
+ Returns a copy of this object
255
255
 
256
- :return: A copy of self
256
+ :return: A copy of self
257
257
  """
258
258
  retfilters = Filters(self.filter_converter, self.datamodel)
259
259
  retfilters.filters = copy.copy(self.filters)
@@ -262,7 +262,7 @@ class Filters(object):
262
262
 
263
263
  def get_relation_cols(self):
264
264
  """
265
- Returns the filter active FilterRelation cols
265
+ Returns the filter active FilterRelation cols
266
266
  """
267
267
  retlst = []
268
268
  for flt, value in zip(self.filters, self.values):
@@ -272,16 +272,16 @@ class Filters(object):
272
272
 
273
273
  def get_filters_values(self) -> List[Tuple[BaseFilter, Any]]:
274
274
  """
275
- Returns a list of tuples [(FILTER, value),(...,...),....]
275
+ Returns a list of tuples [(FILTER, value),(...,...),....]
276
276
  """
277
277
  return [(flt, value) for flt, value in zip(self.filters, self.values)]
278
278
 
279
279
  def get_filter_value(self, column_name: str) -> Any:
280
280
  """
281
- Returns the filtered value for a certain column
281
+ Returns the filtered value for a certain column
282
282
 
283
- :param column_name: The name of the column that we want the value from
284
- :return: the filter value of the column
283
+ :param column_name: The name of the column that we want the value from
284
+ :return: the filter value of the column
285
285
  """
286
286
  for flt, value in zip(self.filters, self.values):
287
287
  if flt.column_name == column_name:
@@ -294,8 +294,12 @@ class Filters(object):
294
294
  ]
295
295
 
296
296
  def apply_all(self, query):
297
- for flt, value in zip(self.filters, self.values):
298
- query = flt.apply(query, value)
297
+ for flt, values in zip(self.filters, self.values):
298
+ if isinstance(values, list) and flt.arg_name not in {"in", "not_in"}:
299
+ for value in values:
300
+ query = flt.apply(query, value)
301
+ else:
302
+ query = flt.apply(query, values)
299
303
  return query
300
304
 
301
305
  def __repr__(self):
@@ -35,13 +35,13 @@ class GenericColumn(object):
35
35
 
36
36
  class MetaGenericModel(type):
37
37
  """
38
- Meta class for GenericModel
39
- will change default properties:
40
- - instantiates internal '_col_defs' dict with
41
- all the defined columns.
42
- - Define pk property with the name of the primary key column
43
- - Define properties with a list of all column's properties
44
- - Define columns with a list of all column's name
38
+ Meta class for GenericModel
39
+ will change default properties:
40
+ - instantiates internal '_col_defs' dict with
41
+ all the defined columns.
42
+ - Define pk property with the name of the primary key column
43
+ - Define properties with a list of all column's properties
44
+ - Define columns with a list of all column's name
45
45
  """
46
46
 
47
47
  pk = None
@@ -68,18 +68,18 @@ class MetaGenericModel(type):
68
68
 
69
69
  class GenericModel(with_metaclass(MetaGenericModel, object)):
70
70
  """
71
- Generic Model class to define generic purpose models to use
72
- with the framework.
71
+ Generic Model class to define generic purpose models to use
72
+ with the framework.
73
73
 
74
- Use GenericSession much like SQLAlchemy's Session Class.
75
- Extend GenericSession to implement specific engine features.
74
+ Use GenericSession much like SQLAlchemy's Session Class.
75
+ Extend GenericSession to implement specific engine features.
76
76
 
77
- Define your models like::
77
+ Define your models like::
78
78
 
79
- class MyGenericModel(GenericModel):
80
- id = GenericColumn(int, primary_key=True)
81
- age = GenericColumn(int)
82
- name = GenericColumn(str)
79
+ class MyGenericModel(GenericModel):
80
+ id = GenericColumn(int, primary_key=True)
81
+ age = GenericColumn(int)
82
+ name = GenericColumn(str)
83
83
 
84
84
  """
85
85
 
@@ -111,13 +111,13 @@ class GenericModel(with_metaclass(MetaGenericModel, object)):
111
111
 
112
112
  class GenericSession(object):
113
113
  """
114
- This class is a base, you should subclass it
115
- to implement your own generic data source.
114
+ This class is a base, you should subclass it
115
+ to implement your own generic data source.
116
116
 
117
- Override at least the **all** method.
117
+ Override at least the **all** method.
118
118
 
119
- **GenericSession** will implement filter and orders
120
- based on your data generation on the **all** method.
119
+ **GenericSession** will implement filter and orders
120
+ based on your data generation on the **all** method.
121
121
  """
122
122
 
123
123
  def __init__(self):
@@ -131,20 +131,20 @@ class GenericSession(object):
131
131
 
132
132
  def clear(self):
133
133
  """
134
- Deletes the entire store
134
+ Deletes the entire store
135
135
  """
136
136
  self.store = dict()
137
137
 
138
138
  def delete_all(self, model_cls):
139
139
  """
140
- Deletes all objects of type model_cls
140
+ Deletes all objects of type model_cls
141
141
  """
142
142
  self.store[model_cls._name] = []
143
143
 
144
144
  def get(self, pk):
145
145
  """
146
- Returns the object for the key
147
- Override it for efficiency.
146
+ Returns the object for the key
147
+ Override it for efficiency.
148
148
  """
149
149
  for item in self.store.get(self.query_class):
150
150
  # coverts pk value to correct type
@@ -154,7 +154,7 @@ class GenericSession(object):
154
154
 
155
155
  def query(self, model_cls):
156
156
  """
157
- SQLAlchemy query like method
157
+ SQLAlchemy query like method
158
158
  """
159
159
  self._filters_cmd = list()
160
160
  self.query_filters = list()
@@ -350,8 +350,8 @@ class GenericSession(object):
350
350
 
351
351
  def all(self):
352
352
  """
353
- SQLA like 'all' method, will populate all rows and apply all
354
- filters and orders to it.
353
+ SQLA like 'all' method, will populate all rows and apply all
354
+ filters and orders to it.
355
355
  """
356
356
  items = list()
357
357
  if not self._filters_cmd:
@@ -396,7 +396,7 @@ class PSModel(GenericModel):
396
396
 
397
397
  class PSSession(GenericSession):
398
398
  regexp = (
399
- "(\w+) +(\w+) +(\w+) +(\w+) +(\w+:\w+|\w+) (\?|tty\w+) +(\w+:\w+:\w+) +(.+)\n"
399
+ r"(\w+) +(\w+) +(\w+) +(\w+) +(\w+:\w+|\w+) (\?|tty\w+) +(\w+:\w+:\w+) +(.+)\n"
400
400
  )
401
401
 
402
402
  def add_object(self, line):
@@ -78,8 +78,8 @@ class FilterStartsWith(BaseFilter):
78
78
 
79
79
  class GenericFilterConverter(BaseFilterConverter):
80
80
  """
81
- Class for converting columns into a supported list of filters
82
- specific for SQLAlchemy.
81
+ Class for converting columns into a supported list of filters
82
+ specific for SQLAlchemy.
83
83
 
84
84
  """
85
85
 
@@ -107,6 +107,14 @@ class GenericFilterConverter(BaseFilterConverter):
107
107
  FilterStartsWith,
108
108
  ],
109
109
  ),
110
- ("is_integer", [FilterEqual, FilterNotEqual, FilterGreater, FilterSmaller]),
110
+ (
111
+ "is_integer",
112
+ [
113
+ FilterEqual,
114
+ FilterNotEqual,
115
+ FilterGreater,
116
+ FilterSmaller,
117
+ ],
118
+ ),
111
119
  ("is_date", [FilterEqual, FilterNotEqual, FilterGreater, FilterSmaller]),
112
120
  )
@@ -9,7 +9,6 @@ def _include_filters(obj):
9
9
 
10
10
 
11
11
  class GenericInterface(BaseInterface):
12
-
13
12
  filter_converter_class = filters.GenericFilterConverter
14
13
 
15
14
  def __init__(self, obj, session=None):
@@ -25,7 +24,6 @@ class GenericInterface(BaseInterface):
25
24
  page=None,
26
25
  page_size=None,
27
26
  ):
28
-
29
27
  query = self.session.query(self.obj)
30
28
  if filters:
31
29
  query = filters.apply_all(query)
@@ -68,7 +66,7 @@ class GenericInterface(BaseInterface):
68
66
 
69
67
  def get_keys(self, lst):
70
68
  """
71
- return a list of pk values from object list
69
+ return a list of pk values from object list
72
70
  """
73
71
  pk_name = self.get_pk_name()
74
72
  return [getattr(item, pk_name) for item in lst]