brilliance-admin 0.44.6__tar.gz → 0.44.7__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 (86) hide show
  1. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/PKG-INFO +1 -1
  2. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/views/autocomplete.py +1 -1
  3. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/views/table.py +5 -5
  4. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/autocomplete.py +6 -1
  5. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/table/create.py +2 -0
  6. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/table/delete.py +1 -1
  7. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/table/list.py +18 -6
  8. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/table/retrieve.py +14 -5
  9. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/table/update.py +2 -0
  10. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/locales/en.yml +1 -1
  11. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/locales/ru.yml +1 -1
  12. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/admin_schema.py +4 -2
  13. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/table/category_table.py +10 -7
  14. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin.egg-info/PKG-INFO +1 -1
  15. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/pyproject.toml +1 -1
  16. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/tests/test_sqlalcmeny_crud.py +75 -1
  17. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/tests/test_sqlalcmeny_filters.py +10 -0
  18. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/LICENSE +0 -0
  19. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/README.md +0 -0
  20. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/__init__.py +0 -0
  21. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/__init__.py +0 -0
  22. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/routers.py +0 -0
  23. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/utils.py +0 -0
  24. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/views/__init__.py +0 -0
  25. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/views/auth.py +0 -0
  26. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/views/graphs.py +0 -0
  27. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/views/index.py +0 -0
  28. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/views/schema.py +0 -0
  29. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/api/views/settings.py +0 -0
  30. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/auth.py +0 -0
  31. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/docs.py +0 -0
  32. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/exceptions.py +0 -0
  33. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/__init__.py +0 -0
  34. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/__init__.py +0 -0
  35. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/auth.py +0 -0
  36. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/fields.py +0 -0
  37. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/fields_schema.py +0 -0
  38. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/table/__init__.py +0 -0
  39. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/integrations/sqlalchemy/table/base.py +0 -0
  40. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/__init__.py +0 -0
  41. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/category.py +0 -0
  42. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/graphs/__init__.py +0 -0
  43. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/graphs/category_graphs.py +0 -0
  44. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/table/__init__.py +0 -0
  45. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/table/admin_action.py +0 -0
  46. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/table/fields/__init__.py +0 -0
  47. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/table/fields/base.py +0 -0
  48. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/table/fields/function_field.py +0 -0
  49. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/table/fields_schema.py +0 -0
  50. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/schema/table/table_models.py +0 -0
  51. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/index-BV43pxcV.js +0 -0
  52. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/index-P_wdMBbz.css +0 -0
  53. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/materialdesignicons-webfont-CYDMK1kx.woff2 +0 -0
  54. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/materialdesignicons-webfont-CgCzGbLl.woff +0 -0
  55. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/materialdesignicons-webfont-D3kAzl71.ttf +0 -0
  56. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/materialdesignicons-webfont-DttUABo4.eot +0 -0
  57. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/dark-first/content.min.css +0 -0
  58. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/dark-first/skin.min.css +0 -0
  59. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/dark-slim/content.min.css +0 -0
  60. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/dark-slim/skin.min.css +0 -0
  61. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/img/example.png +0 -0
  62. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/img/tinymce.woff2 +0 -0
  63. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/lightgray/content.min.css +0 -0
  64. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/lightgray/fonts/tinymce.woff +0 -0
  65. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/lightgray/skin.min.css +0 -0
  66. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/plugins/accordion/css/accordion.css +0 -0
  67. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/plugins/accordion/plugin.js +0 -0
  68. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/plugins/codesample/css/prism.css +0 -0
  69. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/plugins/customLink/css/link.css +0 -0
  70. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/plugins/customLink/plugin.js +0 -0
  71. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/tinymce/tinymce.min.js +0 -0
  72. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/static/vanilla-picker-B6E6ObS_.js +0 -0
  73. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/templates/index.html +0 -0
  74. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/translations.py +0 -0
  75. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin/utils.py +0 -0
  76. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin.egg-info/SOURCES.txt +0 -0
  77. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin.egg-info/dependency_links.txt +0 -0
  78. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin.egg-info/requires.txt +0 -0
  79. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/brilliance_admin.egg-info/top_level.txt +0 -0
  80. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/setup.cfg +0 -0
  81. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/tests/test_action.py +0 -0
  82. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/tests/test_payments_fields_schema.py +0 -0
  83. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/tests/test_settings.py +0 -0
  84. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/tests/test_sqlalcmeny_auth.py +0 -0
  85. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/tests/test_sqlalcmeny_schema.py +0 -0
  86. {brilliance_admin-0.44.6 → brilliance_admin-0.44.7}/tests/test_translations.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brilliance-admin
3
- Version: 0.44.6
3
+ Version: 0.44.7
4
4
  Summary: Simple and lightweight data managment framework powered by FastAPI and Vue3 Vuetify all-in-one. Some call it heavenly in its brilliance.
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.10
@@ -23,7 +23,7 @@ async def autocomplete(request: Request, group: str, category: str, data: Autoco
23
23
  context = {'language_context': language_context}
24
24
 
25
25
  try:
26
- result: AutocompleteResult = await schema_category.autocomplete(data, user, language_context)
26
+ result: AutocompleteResult = await schema_category.autocomplete(data, user, language_context, schema)
27
27
  except AdminAPIException as e:
28
28
  return JSONResponse(e.get_error().model_dump(mode='json', context=context), status_code=e.status_code)
29
29
  except Exception as e:
@@ -30,7 +30,7 @@ async def table_list(request: Request, group: str, category: str, list_data: Lis
30
30
  context = {'language_context': language_context}
31
31
 
32
32
  try:
33
- result: TableListResult = await schema_category.get_list(list_data, user, language_context)
33
+ result: TableListResult = await schema_category.get_list(list_data, user, language_context, schema)
34
34
  except AdminAPIException as e:
35
35
  return JSONResponse(e.get_error().model_dump(mode='json', context=context), status_code=e.status_code)
36
36
 
@@ -54,7 +54,7 @@ async def table_retrieve(request: Request, group: str, category: str, pk: Any) -
54
54
  context = {'language_context': language_context}
55
55
 
56
56
  try:
57
- result: RetrieveResult = await schema_category.retrieve(pk, user, language_context)
57
+ result: RetrieveResult = await schema_category.retrieve(pk, user, language_context, schema)
58
58
  except AdminAPIException as e:
59
59
  return JSONResponse(e.get_error().model_dump(mode='json', context=context), status_code=e.status_code)
60
60
 
@@ -77,7 +77,7 @@ async def table_create(request: Request, group: str, category: str) -> CreateRes
77
77
  context = {'language_context': language_context}
78
78
 
79
79
  try:
80
- result: CreateResult = await schema_category.create(await request.json(), user, language_context)
80
+ result: CreateResult = await schema_category.create(await request.json(), user, language_context, schema)
81
81
  except AdminAPIException as e:
82
82
  return JSONResponse(e.get_error().model_dump(mode='json', context=context), status_code=e.status_code)
83
83
 
@@ -100,7 +100,7 @@ async def table_update(request: Request, group: str, category: str, pk: Any) ->
100
100
  context = {'language_context': language_context}
101
101
 
102
102
  try:
103
- result: UpdateResult = await schema_category.update(pk, await request.json(), user, language_context)
103
+ result: UpdateResult = await schema_category.update(pk, await request.json(), user, language_context, schema)
104
104
  except AdminAPIException as e:
105
105
  return JSONResponse(e.get_error().model_dump(mode='json', context=context), status_code=e.status_code)
106
106
 
@@ -129,7 +129,7 @@ async def table_action(
129
129
  try:
130
130
  # pylint: disable=protected-access
131
131
  result: ActionResult = await schema_category._perform_action(
132
- request, action, action_data, language_context, user,
132
+ request, action, action_data, language_context, user, schema,
133
133
  )
134
134
  except AdminAPIException as e:
135
135
  return JSONResponse(e.get_error().model_dump(mode='json', context=context), status_code=e.status_code)
@@ -1,11 +1,16 @@
1
1
  from brilliance_admin.auth import UserABC
2
+ from brilliance_admin.schema.admin_schema import AdminSchema
2
3
  from brilliance_admin.schema.table.table_models import AutocompleteData, AutocompleteResult
3
4
  from brilliance_admin.translations import LanguageContext
4
5
 
5
6
 
6
7
  class SQLAlchemyAdminAutocompleteMixin:
7
8
  async def autocomplete(
8
- self, data: AutocompleteData, user: UserABC, language_context: LanguageContext,
9
+ self,
10
+ data: AutocompleteData,
11
+ user: UserABC,
12
+ language_context: LanguageContext,
13
+ admin_schema: AdminSchema,
9
14
  ) -> AutocompleteResult:
10
15
  form_schema = None
11
16
 
@@ -1,6 +1,7 @@
1
1
  from brilliance_admin import schema
2
2
  from brilliance_admin.auth import UserABC
3
3
  from brilliance_admin.exceptions import AdminAPIException, APIError
4
+ from brilliance_admin.schema.admin_schema import AdminSchema
4
5
  from brilliance_admin.translations import LanguageContext
5
6
  from brilliance_admin.translations import TranslateText as _
6
7
  from brilliance_admin.utils import get_logger
@@ -16,6 +17,7 @@ class SQLAlchemyAdminCreate:
16
17
  data: dict,
17
18
  user: UserABC,
18
19
  language_context: LanguageContext,
20
+ admin_schema: AdminSchema,
19
21
  ) -> schema.CreateResult:
20
22
  if not self.has_create:
21
23
  raise AdminAPIException(APIError(message=_('errors.method_not_allowed')), status_code=500)
@@ -12,7 +12,7 @@ class SQLAlchemyDeleteAction:
12
12
  base_color='red-lighten-2',
13
13
  variant='outlined',
14
14
  )
15
- async def delete(self, action_data: ActionData):
15
+ async def delete(self, *args, action_data: ActionData, **kwargs):
16
16
  if not self.has_delete:
17
17
  raise AdminAPIException(APIError(message=_('errors.method_not_allowed')), status_code=500)
18
18
  return ActionResult(message=ActionMessage(_('deleted_successfully')))
@@ -1,6 +1,7 @@
1
1
  from brilliance_admin import auth, schema
2
2
  from brilliance_admin.exceptions import AdminAPIException, APIError, FieldError
3
3
  from brilliance_admin.integrations.sqlalchemy.fields_schema import SQLAlchemyFieldsSchema
4
+ from brilliance_admin.schema.admin_schema import AdminSchema
4
5
  from brilliance_admin.translations import LanguageContext
5
6
  from brilliance_admin.translations import TranslateText as _
6
7
  from brilliance_admin.utils import get_logger
@@ -88,6 +89,7 @@ class SQLAlchemyAdminListMixin:
88
89
  list_data: schema.ListData,
89
90
  user: auth.UserABC,
90
91
  language_context: LanguageContext,
92
+ admin_schema: AdminSchema,
91
93
  ) -> schema.TableListResult:
92
94
  # pylint: disable=import-outside-toplevel
93
95
  from sqlalchemy import exc, func, select
@@ -120,7 +122,10 @@ class SQLAlchemyAdminListMixin:
120
122
  'list_data': list_data,
121
123
  }
122
124
  )
123
- raise AdminAPIException(APIError(message=_('errors.filters_exception'), code='filters_exception'), status_code=500) from e
125
+ msg = _('errors.filters_exception') % {
126
+ 'error': str(e) if admin_schema.debug else type(e).__name__,
127
+ }
128
+ raise AdminAPIException(APIError(message=msg, code='filters_exception'), status_code=500) from e
124
129
 
125
130
  try:
126
131
  async with self.db_async_session() as session:
@@ -163,7 +168,9 @@ class SQLAlchemyAdminListMixin:
163
168
  'list_data': list_data,
164
169
  }
165
170
  )
166
- msg = _('errors.db_error_list') % {'error_type': type(e).__name__}
171
+ msg = _('errors.db_error_list') % {
172
+ 'error_type': str(e) if admin_schema.debug else type(e).__name__,
173
+ }
167
174
  raise AdminAPIException(
168
175
  APIError(message=msg, code='db_error_list'), status_code=500,
169
176
  ) from e
@@ -182,15 +189,20 @@ class SQLAlchemyAdminListMixin:
182
189
  'SQLAlchemy %s list %s serialize field error: %s',
183
190
  type(self).__name__, self.model.__name__, e,
184
191
  )
185
- msg = _('serialize_error.field_error') % {'error': e.message, 'field_slug': e.field_slug}
186
- raise AdminAPIException(APIError(message=msg, code='filters_exception'), status_code=500) from e
192
+ msg = _('serialize_error.field_error') % {
193
+ 'error': e.message,
194
+ 'field_slug': e.field_slug,
195
+ }
196
+ raise AdminAPIException(APIError(message=msg, code='field_error'), status_code=500) from e
187
197
 
188
198
  except Exception as e:
189
199
  logger.exception(
190
200
  'SQLAlchemy %s list %s serialize error: %s',
191
201
  type(self).__name__, self.model.__name__, e,
192
202
  )
193
- msg = _('serialize_error.unexpected_error') % {'error': str(e)}
194
- raise AdminAPIException(APIError(message=msg, code='filters_exception'), status_code=500) from e
203
+ msg = _('serialize_error.unexpected_error') % {
204
+ 'error': str(e) if admin_schema.debug else type(e).__name__,
205
+ }
206
+ raise AdminAPIException(APIError(message=msg, code='unexpected_error'), status_code=500) from e
195
207
 
196
208
  return schema.TableListResult(data=data, total_count=int(total_count or 0))
@@ -3,6 +3,7 @@ from typing import Any
3
3
  from brilliance_admin import auth, schema
4
4
  from brilliance_admin.exceptions import AdminAPIException, APIError, FieldError
5
5
  from brilliance_admin.integrations.sqlalchemy.fields_schema import SQLAlchemyFieldsSchema
6
+ from brilliance_admin.schema.admin_schema import AdminSchema
6
7
  from brilliance_admin.translations import LanguageContext
7
8
  from brilliance_admin.translations import TranslateText as _
8
9
  from brilliance_admin.utils import get_logger
@@ -20,6 +21,7 @@ class SQLAlchemyAdminRetrieveMixin:
20
21
  pk: Any,
21
22
  user: auth.UserABC,
22
23
  language_context: LanguageContext,
24
+ admin_schema: AdminSchema,
23
25
  ) -> schema.RetrieveResult:
24
26
  if not self.has_delete:
25
27
  raise AdminAPIException(APIError(message=_('errors.method_not_allowed')), status_code=500)
@@ -42,7 +44,9 @@ class SQLAlchemyAdminRetrieveMixin:
42
44
  'SQLAlchemy %s retrieve %s #%s db error: %s',
43
45
  type(self).__name__, self.model.__name__, pk, e,
44
46
  )
45
- msg = _('errors.db_error_retrieve') % {'error_type': type(e).__name__}
47
+ msg = _('errors.db_error_retrieve') % {
48
+ 'error_type': str(e) if admin_schema.debug else type(e).__name__,
49
+ }
46
50
  raise AdminAPIException(
47
51
  APIError(message=msg, code='db_error_retrieve'), status_code=500,
48
52
  ) from e
@@ -64,16 +68,21 @@ class SQLAlchemyAdminRetrieveMixin:
64
68
  'SQLAlchemy %s retrieve %s #%s serialize field error: %s',
65
69
  type(self).__name__, self.model.__name__, pk, e,
66
70
  )
67
- msg = _('serialize_error.field_error') % {'error': e.message, 'field_slug': e.field_slug}
68
- raise AdminAPIException(APIError(message=msg, code='filters_exception'), status_code=500) from e
71
+ msg = _('serialize_error.field_error') % {
72
+ 'error': e.message,
73
+ 'field_slug': e.field_slug,
74
+ }
75
+ raise AdminAPIException(APIError(message=msg, code='field_error'), status_code=500) from e
69
76
 
70
77
  except Exception as e:
71
78
  logger.exception(
72
79
  'SQLAlchemy %s list %s #%s serialize error: %s',
73
80
  type(self).__name__, self.model.__name__, pk, e,
74
81
  )
75
- msg = _('serialize_error.unexpected_error') % {'error': str(e)}
76
- raise AdminAPIException(APIError(message=msg, code='filters_exception'), status_code=500) from e
82
+ msg = _('serialize_error.unexpected_error') % {
83
+ 'error': str(e) if admin_schema.debug else type(e).__name__,
84
+ }
85
+ raise AdminAPIException(APIError(message=msg, code='unexpected_error'), status_code=500) from e
77
86
 
78
87
  logger.debug(
79
88
  '%s model %s #%s retrieved by %s',
@@ -2,6 +2,7 @@ from typing import Any
2
2
 
3
3
  from brilliance_admin import auth, schema
4
4
  from brilliance_admin.exceptions import AdminAPIException, APIError
5
+ from brilliance_admin.schema.admin_schema import AdminSchema
5
6
  from brilliance_admin.translations import LanguageContext
6
7
  from brilliance_admin.translations import TranslateText as _
7
8
  from brilliance_admin.utils import get_logger
@@ -19,6 +20,7 @@ class SQLAlchemyAdminUpdate:
19
20
  data: dict,
20
21
  user: auth.UserABC,
21
22
  language_context: LanguageContext,
23
+ admin_schema: AdminSchema,
22
24
  ) -> schema.UpdateResult:
23
25
  if not self.has_update:
24
26
  raise AdminAPIException(APIError(message=_('errors.method_not_allowed')), status_code=500)
@@ -12,7 +12,7 @@ errors:
12
12
  db_error_list: 'Failed to retrieve table data from the database: %(error_type)s'
13
13
 
14
14
  connection_refused_error: 'Database connection error: %(error)s'
15
- filters_exception: 'An unknown technical error occurred while filtering data.'
15
+ filters_exception: 'An unknown technical error occurred while filtering data: %(error_type)s'
16
16
  method_not_allowed: 'Error, method not allowed. This action is not permitted.'
17
17
  filter_error: 'An error occurred during filtering: {error}'
18
18
  bad_type_error: 'Invalid data type: %(type)s but %(expected)s expected'
@@ -12,7 +12,7 @@ errors:
12
12
  db_error_list: 'Ошибка получения данных таблицы из базы данных: %(error_type)s'
13
13
 
14
14
  connection_refused_error: 'Ошибка подключения к базе данных: %(error)s'
15
- filters_exception: 'Произошла неизвестная техническая ошибка при фильтрации данных.'
15
+ filters_exception: 'Произошла неизвестная техническая ошибка при фильтрации данных: %(error_type)s'
16
16
  method_not_allowed: 'Ошибка, данный метод недоступен.'
17
17
  filter_error: 'Проишла ошибка при фильтрации: %(error)s'
18
18
  bad_type_error: 'Некорректный тип данных: %(type)s; ожидается %(expected)s'
@@ -68,6 +68,8 @@ class AdminSchema:
68
68
 
69
69
  language_manager: LanguageManager | None = None
70
70
 
71
+ debug: bool = False
72
+
71
73
  def __post_init__(self):
72
74
  for category in self.categories:
73
75
  if not issubclass(category.__class__, BaseCategory):
@@ -122,8 +124,6 @@ class AdminSchema:
122
124
  languages=languages,
123
125
  )
124
126
 
125
- # pylint: disable=too-many-arguments
126
- # pylint: disable=too-many-positional-arguments
127
127
  def generate_app(
128
128
  self,
129
129
  debug=False,
@@ -133,6 +133,8 @@ class AdminSchema:
133
133
  include_docs=False,
134
134
  include_redoc=False,
135
135
  ) -> FastAPI:
136
+ self.debug = debug
137
+
136
138
  # pylint: disable=unused-variable
137
139
  language_context = self.get_language_context(language_slug=None)
138
140
 
@@ -8,8 +8,8 @@ from pydantic import Field
8
8
 
9
9
  from brilliance_admin.auth import UserABC
10
10
  from brilliance_admin.exceptions import AdminAPIException, APIError
11
- from brilliance_admin.schema.category import BaseCategory
12
- from brilliance_admin.schema.category import TableInfoSchemaData
11
+ from brilliance_admin.schema.admin_schema import AdminSchema
12
+ from brilliance_admin.schema.category import BaseCategory, TableInfoSchemaData
13
13
  from brilliance_admin.schema.table.admin_action import ActionData, ActionResult
14
14
  from brilliance_admin.schema.table.fields_schema import FieldsSchema
15
15
  from brilliance_admin.schema.table.table_models import AutocompleteData, AutocompleteResult, ListData, TableListResult
@@ -130,6 +130,7 @@ class CategoryTable(BaseCategory):
130
130
  action_data: ActionData,
131
131
  language_context: LanguageContext,
132
132
  user: UserABC,
133
+ admin_schema: AdminSchema,
133
134
  ) -> ActionResult:
134
135
  action_fn = self._get_action_fn(action)
135
136
  if action_fn is None:
@@ -156,7 +157,7 @@ class CategoryTable(BaseCategory):
156
157
 
157
158
  return result
158
159
 
159
- async def autocomplete(self, data: AutocompleteData, user: UserABC) -> AutocompleteResult:
160
+ async def autocomplete(self, data: AutocompleteData, user: UserABC, schema: AdminSchema) -> AutocompleteResult:
160
161
  """
161
162
  Retrieves list of found options to select.
162
163
  """
@@ -164,14 +165,16 @@ class CategoryTable(BaseCategory):
164
165
 
165
166
  # pylint: disable=too-many-arguments
166
167
  @abc.abstractmethod
167
- async def get_list(self, list_data: ListData, user: UserABC, language_context: LanguageContext) -> TableListResult:
168
+ async def get_list(
169
+ self, list_data: ListData, user: UserABC, language_context: LanguageContext, admin_schema: AdminSchema
170
+ ) -> TableListResult:
168
171
  raise NotImplementedError()
169
172
 
170
- # async def retrieve(self, pk: Any, user: UserABC) -> RetrieveResult:
173
+ # async def retrieve(self, pk: Any, user: UserABC, language_context: LanguageContext, admin_schema: AdminSchema) -> RetrieveResult:
171
174
  # raise NotImplementedError()
172
175
 
173
- # async def create(self, data: dict, user: UserABC) -> CreateResult:
176
+ # async def create(self, data: dict, user: UserABC, language_context: LanguageContext, admin_schema: AdminSchema) -> CreateResult:
174
177
  # raise NotImplementedError()
175
178
 
176
- # async def update(self, pk: Any, data: dict, user: UserABC) -> UpdateResult:
179
+ # async def update(self, pk: Any, data: dict, user: UserABC, language_context: LanguageContext, admin_schema: AdminSchema) -> UpdateResult:
177
180
  # raise NotImplementedError()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brilliance-admin
3
- Version: 0.44.6
3
+ Version: 0.44.7
4
4
  Summary: Simple and lightweight data managment framework powered by FastAPI and Vue3 Vuetify all-in-one. Some call it heavenly in its brilliance.
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.10
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "brilliance-admin"
3
- version = "0.44.6"
3
+ version = "0.44.7"
4
4
  description = 'Simple and lightweight data managment framework powered by FastAPI and Vue3 Vuetify all-in-one. Some call it heavenly in its brilliance.'
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -5,9 +5,11 @@ from sqlalchemy import select
5
5
  from sqlalchemy.orm import selectinload
6
6
 
7
7
  from brilliance_admin import auth, schema, sqlalchemy
8
+ from brilliance_admin.exceptions import AdminAPIException
9
+ from brilliance_admin.schema import admin_schema
8
10
  from brilliance_admin.translations import TranslateText
9
11
  from example.sections.models import (
10
- Currency, CurrencyFactory, MerchantFactory, Terminal, TerminalFactory, TerminalStatuses)
12
+ Currency, CurrencyFactory, Merchant, MerchantFactory, Terminal, TerminalFactory, TerminalStatuses)
11
13
  from tests.test_sqlalcmeny_schema import FIELDS
12
14
 
13
15
 
@@ -42,11 +44,37 @@ async def test_create(sqlite_sessionmaker, language_context):
42
44
  data=create_data,
43
45
  user=user,
44
46
  language_context=language_context,
47
+ admin_schema=admin_schema,
45
48
  )
46
49
 
47
50
  assert create_result.pk == 1
48
51
 
49
52
 
53
+ @pytest.mark.asyncio
54
+ async def test_create_bad_fk(sqlite_sessionmaker, language_context):
55
+ category = get_category(sqlite_sessionmaker)
56
+ user = auth.UserABC(username="test")
57
+ merchant = await MerchantFactory()
58
+ currency = await CurrencyFactory()
59
+
60
+ create_data = {
61
+ 'manager_id': 1,
62
+ 'merchant_id': 100,
63
+ 'currency_id': currency.id,
64
+ 'status': 'test',
65
+ 'description': 'test',
66
+ 'title': 'test',
67
+ }
68
+ with pytest.raises(AdminAPIException) as e:
69
+ schema.CreateResult = await category.create(
70
+ data=create_data,
71
+ user=user,
72
+ language_context=language_context,
73
+ admin_schema=admin_schema,
74
+ )
75
+ assert e.value.get_error().message == 'NOT NULL constraint failed: terminal.merchant_id'
76
+
77
+
50
78
  @pytest.mark.asyncio
51
79
  async def test_retrieve(sqlite_sessionmaker, language_context):
52
80
  category = get_category(sqlite_sessionmaker)
@@ -67,6 +95,7 @@ async def test_retrieve(sqlite_sessionmaker, language_context):
67
95
  pk=terminal.id,
68
96
  user=user,
69
97
  language_context=language_context,
98
+ admin_schema=admin_schema,
70
99
  )
71
100
  expected_data = {
72
101
  'manager_id': mock.ANY,
@@ -127,6 +156,7 @@ async def test_retrieve_currency(sqlite_sessionmaker, language_context):
127
156
  pk=currency.id,
128
157
  user=user,
129
158
  language_context=language_context,
159
+ admin_schema=admin_schema,
130
160
  )
131
161
  expected_data = {
132
162
  'id': currency.id,
@@ -138,6 +168,46 @@ async def test_retrieve_currency(sqlite_sessionmaker, language_context):
138
168
  assert retrieve_result.data == expected_data, retrieve_result.data
139
169
 
140
170
 
171
+ @pytest.mark.asyncio
172
+ async def test_create_bad_json(sqlite_sessionmaker, language_context):
173
+ category = sqlalchemy.SQLAlchemyAdmin(
174
+ model=Merchant,
175
+ db_async_session=sqlite_sessionmaker,
176
+ table_schema=sqlalchemy.SQLAlchemyFieldsSchema(
177
+ model=Merchant,
178
+ fields=[
179
+ 'title',
180
+ 'provider_settings',
181
+ ],
182
+ ),
183
+ )
184
+ user = auth.UserABC(username="test")
185
+ create_data = {
186
+ 'title': 'test',
187
+ 'provider_settings': 'not json',
188
+ }
189
+ with pytest.raises(AdminAPIException) as e:
190
+ await category.create(
191
+ data=create_data,
192
+ user=user,
193
+ language_context=language_context,
194
+ admin_schema=admin_schema,
195
+ )
196
+ context = {'language_context': language_context}
197
+ errors = {
198
+ 'code': 'validation_error',
199
+ 'field_errors': {
200
+ 'provider_settings': {
201
+ 'code': None,
202
+ 'field_slug': None,
203
+ 'message': "Некорректный тип данных: <class 'str'>; ожидается JSON",
204
+ },
205
+ },
206
+ 'message': 'Validation error',
207
+ }
208
+ assert e.value.get_error().model_dump(context=context) == errors
209
+
210
+
141
211
  @pytest.mark.asyncio
142
212
  async def test_list(sqlite_sessionmaker, language_context):
143
213
  category = get_category(sqlite_sessionmaker)
@@ -160,6 +230,7 @@ async def test_list(sqlite_sessionmaker, language_context):
160
230
  ),
161
231
  user=user,
162
232
  language_context=language_context,
233
+ admin_schema=admin_schema,
163
234
  )
164
235
  data = [
165
236
  {
@@ -212,6 +283,7 @@ async def test_update_related_one(sqlite_sessionmaker, language_context):
212
283
  data=update_data,
213
284
  user=user,
214
285
  language_context=language_context,
286
+ admin_schema=admin_schema,
215
287
  )
216
288
  assert update_result == schema.UpdateResult(pk=terminal.id)
217
289
 
@@ -253,6 +325,7 @@ async def test_update_related_many(sqlite_sessionmaker, language_context):
253
325
  data=update_data,
254
326
  user=user,
255
327
  language_context=language_context,
328
+ admin_schema=admin_schema,
256
329
  )
257
330
  assert update_result == schema.UpdateResult(pk=currency_rub.id)
258
331
 
@@ -285,5 +358,6 @@ async def test_autocomplete(sqlite_sessionmaker, language_context):
285
358
  ),
286
359
  user=user,
287
360
  language_context=language_context,
361
+ admin_schema=admin_schema,
288
362
  )
289
363
  assert autocomplete_result == schema.AutocompleteResult()
@@ -3,6 +3,7 @@ from datetime import datetime
3
3
  import pytest
4
4
 
5
5
  from brilliance_admin import auth, schema, sqlalchemy
6
+ from brilliance_admin.schema import admin_schema
6
7
  from example.sections.models import Currency, CurrencyFactory, MerchantFactory, Terminal, TerminalFactory
7
8
 
8
9
 
@@ -33,6 +34,7 @@ async def test_list_filter(sqlite_sessionmaker, language_context):
33
34
  list_data=schema.ListData(filters={'id': terminal_1.id}),
34
35
  user=user,
35
36
  language_context=language_context,
37
+ admin_schema=admin_schema,
36
38
  )
37
39
  assert list_result == schema.TableListResult(
38
40
  data=[{'id': terminal_1.id}], total_count=1
@@ -42,6 +44,7 @@ async def test_list_filter(sqlite_sessionmaker, language_context):
42
44
  list_data=schema.ListData(filters={'title': 'Test terminal second'}),
43
45
  user=user,
44
46
  language_context=language_context,
47
+ admin_schema=admin_schema,
45
48
  )
46
49
  assert list_result == schema.TableListResult(
47
50
  data=[{'id': terminal_2.id}], total_count=1
@@ -51,6 +54,7 @@ async def test_list_filter(sqlite_sessionmaker, language_context):
51
54
  list_data=schema.ListData(filters={'title': 'Test%'}),
52
55
  user=user,
53
56
  language_context=language_context,
57
+ admin_schema=admin_schema,
54
58
  )
55
59
  assert list_result == schema.TableListResult(
56
60
  data=[{'id': terminal_2.id}, {'id': terminal_1.id}], total_count=2
@@ -66,6 +70,7 @@ async def test_list_filter(sqlite_sessionmaker, language_context):
66
70
  list_data=schema.ListData(filters={'created_at': {'from': '2022-12-04T18:55:00', 'to': '2023-12-17T18:55:00'}}),
67
71
  user=user,
68
72
  language_context=language_context,
73
+ admin_schema=admin_schema,
69
74
  )
70
75
  assert list_result == schema.TableListResult(
71
76
  data=[{'id': terminal_old.id}], total_count=1
@@ -96,6 +101,7 @@ async def test_list_search(sqlite_sessionmaker, language_context):
96
101
  list_data=schema.ListData(search='Test%'),
97
102
  user=user,
98
103
  language_context=language_context,
104
+ admin_schema=admin_schema,
99
105
  )
100
106
  assert list_result == schema.TableListResult(
101
107
  data=[{'id': terminal_2.id}, {'id': terminal_1.id}], total_count=2,
@@ -133,6 +139,7 @@ async def test_filter_related_one(sqlite_sessionmaker, language_context):
133
139
  }),
134
140
  user=user,
135
141
  language_context=language_context,
142
+ admin_schema=admin_schema,
136
143
  )
137
144
  assert list_result == schema.TableListResult(
138
145
  data=[{'id': currency_rub.id}], total_count=1
@@ -169,6 +176,7 @@ async def test_filter_related_many(sqlite_sessionmaker, language_context):
169
176
  }),
170
177
  user=user,
171
178
  language_context=language_context,
179
+ admin_schema=admin_schema,
172
180
  )
173
181
  assert list_result == schema.TableListResult(data=[{'id': terminal_2.id}], total_count=1), 'Фильтр по related'
174
182
 
@@ -208,6 +216,7 @@ async def test_ordering(sqlite_sessionmaker, language_context):
208
216
  list_data=schema.ListData(ordering='id'),
209
217
  user=user,
210
218
  language_context=language_context,
219
+ admin_schema=admin_schema,
211
220
  )
212
221
  assert list_result == schema.TableListResult(
213
222
  data=[{'id': terminal_1.id}, {'id': terminal_2.id, }], total_count=2
@@ -217,6 +226,7 @@ async def test_ordering(sqlite_sessionmaker, language_context):
217
226
  list_data=schema.ListData(ordering='-id'),
218
227
  user=user,
219
228
  language_context=language_context,
229
+ admin_schema=admin_schema,
220
230
  )
221
231
  assert list_result == schema.TableListResult(
222
232
  data=[{'id': terminal_2.id}, {'id': terminal_1.id, }], total_count=2