brilliance-admin 0.44.5__py3-none-any.whl → 0.44.6__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.
@@ -10,6 +10,7 @@ from brilliance_admin.utils import DataclassBase, SupportsStr
10
10
  class FieldError(DataclassBase, Exception):
11
11
  message: SupportsStr = None
12
12
  code: str | None = None
13
+ field_slug: str | None = None
13
14
 
14
15
  def __post_init__(self):
15
16
  if not self.message and not self.code:
@@ -30,12 +30,12 @@ class SQLAlchemyAdminListMixin:
30
30
 
31
31
  if list_data.ordering and ordering not in self.ordering_fields:
32
32
  msg = f'Ordering "{ordering}" is not allowed; available options: {self.ordering_fields} default_ordering: {self.default_ordering}'
33
- raise FieldError(message=msg)
33
+ raise FieldError(message=msg, field_slug='ordering')
34
34
 
35
35
  column = getattr(self.model, ordering, None)
36
36
  if not isinstance(column, InstrumentedAttribute):
37
37
  msg = f'{type(self).__name__} ordering field "{ordering}" not found in model {self.model}'
38
- raise FieldError(message=msg)
38
+ raise FieldError(message=msg, field_slug='ordering')
39
39
 
40
40
  return stmt.order_by(direction(column))
41
41
 
@@ -122,18 +122,10 @@ class SQLAlchemyAdminListMixin:
122
122
  )
123
123
  raise AdminAPIException(APIError(message=_('errors.filters_exception'), code='filters_exception'), status_code=500) from e
124
124
 
125
- data = []
126
-
127
125
  try:
128
126
  async with self.db_async_session() as session:
129
127
  total_count = await session.scalar(count_stmt)
130
128
  records = (await session.execute(stmt)).scalars().all()
131
- for record in records:
132
- line = await self.table_schema.serialize(
133
- record,
134
- extra={"record": record, "user": user},
135
- )
136
- data.append(line)
137
129
 
138
130
  except ConnectionRefusedError as e:
139
131
  logger.exception(
@@ -176,4 +168,29 @@ class SQLAlchemyAdminListMixin:
176
168
  APIError(message=msg, code='db_error_list'), status_code=500,
177
169
  ) from e
178
170
 
171
+ try:
172
+ data = []
173
+ for record in records:
174
+ line = await self.table_schema.serialize(
175
+ record,
176
+ extra={"record": record, "user": user},
177
+ )
178
+ data.append(line)
179
+
180
+ except FieldError as e:
181
+ logger.exception(
182
+ 'SQLAlchemy %s list %s serialize field error: %s',
183
+ type(self).__name__, self.model.__name__, e,
184
+ )
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
187
+
188
+ except Exception as e:
189
+ logger.exception(
190
+ 'SQLAlchemy %s list %s serialize error: %s',
191
+ type(self).__name__, self.model.__name__, e,
192
+ )
193
+ msg = _('serialize_error.unexpected_error') % {'error': str(e)}
194
+ raise AdminAPIException(APIError(message=msg, code='filters_exception'), status_code=500) from e
195
+
179
196
  return schema.TableListResult(data=data, total_count=int(total_count or 0))
@@ -36,18 +36,6 @@ class SQLAlchemyAdminRetrieveMixin:
36
36
  try:
37
37
  async with self.db_async_session() as session:
38
38
  record = (await session.execute(stmt)).scalars().first()
39
- data = await self.table_schema.serialize(
40
- record,
41
- extra={"record": record, "user": user},
42
- )
43
-
44
- except FieldError as e:
45
- logger.exception(
46
- 'SQLAlchemy %s retrieve %s #%s field error: %s',
47
- type(self).__name__, self.model.__name__, pk, e,
48
- )
49
- msg = _('errors.serialize_field_error') % {'error': e.message}
50
- raise AdminAPIException(APIError(message=msg, code='filters_exception'), status_code=500) from e
51
39
 
52
40
  except Exception as e:
53
41
  logger.exception(
@@ -66,6 +54,27 @@ class SQLAlchemyAdminRetrieveMixin:
66
54
  status_code=400,
67
55
  )
68
56
 
57
+ try:
58
+ data = await self.table_schema.serialize(
59
+ record,
60
+ extra={"record": record, "user": user},
61
+ )
62
+ except FieldError as e:
63
+ logger.exception(
64
+ 'SQLAlchemy %s retrieve %s #%s serialize field error: %s',
65
+ type(self).__name__, self.model.__name__, pk, e,
66
+ )
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
69
+
70
+ except Exception as e:
71
+ logger.exception(
72
+ 'SQLAlchemy %s list %s #%s serialize error: %s',
73
+ type(self).__name__, self.model.__name__, pk, e,
74
+ )
75
+ msg = _('serialize_error.unexpected_error') % {'error': str(e)}
76
+ raise AdminAPIException(APIError(message=msg, code='filters_exception'), status_code=500) from e
77
+
69
78
  logger.debug(
70
79
  '%s model %s #%s retrieved by %s',
71
80
  type(self).__name__, self.table_schema.model.__name__, pk, user.username,
@@ -15,9 +15,12 @@ errors:
15
15
  filters_exception: 'An unknown technical error occurred while filtering data.'
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
- serialize_field_error: 'Serialize error: %(error)s'
19
18
  bad_type_error: 'Invalid data type: %(type)s but %(expected)s expected'
20
19
 
20
+ serialize_error:
21
+ field_error: 'Field %(field_slug)s serialize error: %(error)s'
22
+ unexpected_error: 'Unexpected serialize error: %(error)s'
23
+
21
24
  search_help: 'Available search fields: %(fields)s'
22
25
  sqlalchemy_search_help: |
23
26
  <b>Available search fields:</b>
@@ -15,9 +15,12 @@ errors:
15
15
  filters_exception: 'Произошла неизвестная техническая ошибка при фильтрации данных.'
16
16
  method_not_allowed: 'Ошибка, данный метод недоступен.'
17
17
  filter_error: 'Проишла ошибка при фильтрации: %(error)s'
18
- serialize_field_error: 'Ошибка чтения данных: %(error)s'
19
18
  bad_type_error: 'Некорректный тип данных: %(type)s; ожидается %(expected)s'
20
19
 
20
+ serialize_error:
21
+ field_error: 'ошибка чтения поля %(field_slug)s: %(error)s'
22
+ unexpected_error: 'Ошибка обработки данных: %(error)s'
23
+
21
24
  search_help: 'Доступные поля для поиска: %(fields)s'
22
25
  sqlalchemy_search_help: |
23
26
  <b>Доступные поля для поиска:</b>
@@ -159,7 +159,13 @@ class FieldsSchema:
159
159
  result = {}
160
160
  for field_slug, field in self.get_fields().items():
161
161
  value = data.get(field_slug)
162
- result[field_slug] = await field.serialize(value, extra)
162
+
163
+ try:
164
+ result[field_slug] = await field.serialize(value, extra)
165
+ except FieldError as e:
166
+ e.field_slug = field_slug
167
+ raise e
168
+
163
169
  return result
164
170
 
165
171
  async def deserialize(self, data: dict, action: DeserializeAction, extra) -> dict:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: brilliance-admin
3
- Version: 0.44.5
3
+ Version: 0.44.6
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,7 +1,7 @@
1
1
  brilliance_admin/__init__.py,sha256=qxGzLVhFNm2FKL2lVt7bEFb6pTPqyXEQvUsDfyfv6SM,183
2
2
  brilliance_admin/auth.py,sha256=d57XRfLJIbOosLP1-0SCFkePPT8M5WhLcwxu4yW92RA,673
3
3
  brilliance_admin/docs.py,sha256=fKeJKuiCCi1jHRmNcmkuDD6_2di7bwc6-w8V1VCTu0s,1231
4
- brilliance_admin/exceptions.py,sha256=7_L3qVTwdLrzmDJjGv2yqCOVECP35wh0NyTvgjP7ETc,913
4
+ brilliance_admin/exceptions.py,sha256=CJGvpo7EiaX3RVAEUDpwgH_Tuw8kY7tMy57pVcnBxak,947
5
5
  brilliance_admin/translations.py,sha256=I_iSfj05Qv5fbZqDvnnHZGUFsi1wk-J0EXSftKBLw5Q,3850
6
6
  brilliance_admin/utils.py,sha256=M_0WANlb-1NW4aOA33MxOgoRx0GIVJ6w6PCGKAwmflk,5971
7
7
  brilliance_admin/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -25,11 +25,11 @@ brilliance_admin/integrations/sqlalchemy/table/__init__.py,sha256=g_in2pLTi8UQnT
25
25
  brilliance_admin/integrations/sqlalchemy/table/base.py,sha256=-osqhTvqE7YcBxsAjqIUMWyYk1df04GIDmdvtieTXcg,4885
26
26
  brilliance_admin/integrations/sqlalchemy/table/create.py,sha256=8ER27mQe1GGUHpAcWxv0o4HBZ2HyKo2NUAK3m0Jum9o,2771
27
27
  brilliance_admin/integrations/sqlalchemy/table/delete.py,sha256=toH9at-MAWO46K_4YmvkOqXX2-cFANVVhAURiZ-dwWQ,738
28
- brilliance_admin/integrations/sqlalchemy/table/list.py,sha256=zoKp3Xrhnu7km3dexYUXplfvA6GZ9Cid675EmnnW-SE,6777
29
- brilliance_admin/integrations/sqlalchemy/table/retrieve.py,sha256=sOB2c3w-8QLhGBt6N_ltoBHPT7GgohcoXOx4UzQEwu0,2801
28
+ brilliance_admin/integrations/sqlalchemy/table/list.py,sha256=J2zMl5hMYrRoP6zMtVYeHRONefsbwAXKrwjR6nA-4zM,7615
29
+ brilliance_admin/integrations/sqlalchemy/table/retrieve.py,sha256=-UG9eniBcUg8GfEW54B-i4Oi0ELfV8BlV7pQ3W1213Q,3226
30
30
  brilliance_admin/integrations/sqlalchemy/table/update.py,sha256=0BQpkke1ge6snUfdGDBZwpdva446BegXS4uVPzPCWcw,3635
31
- brilliance_admin/locales/en.yml,sha256=47KIaJVUZGq2_zzmabnvwhshajH1eEhqoNKEfaLYLtE,1349
32
- brilliance_admin/locales/ru.yml,sha256=smEM8P000xeNUUu8EmHpycFanG6gctG77PRpLrKz7Jo,1940
31
+ brilliance_admin/locales/en.yml,sha256=GO76VbfqnnsHfn7rPUF-D9s3k3pnYr75UxjZMKDiXo4,1438
32
+ brilliance_admin/locales/ru.yml,sha256=wKlQb8f4Cm_cdeY-MlCRlChit6REx_PNZ6VT6Bm_dQY,2037
33
33
  brilliance_admin/schema/__init__.py,sha256=tZIRTSKFsNOmDqjoAgtYthYrT8ljPvLnYRzfupBLT00,290
34
34
  brilliance_admin/schema/admin_schema.py,sha256=9w88GuogRjdphFuDdx7On553qHTwGoJVCyKpooFSKQ8,6723
35
35
  brilliance_admin/schema/category.py,sha256=D2aIpDyL-2CibkpenNu8uyh4AzOdQ2ArTDltVYS7xZQ,6592
@@ -38,7 +38,7 @@ brilliance_admin/schema/graphs/category_graphs.py,sha256=iTjwjQoZocEfJWJEAdYcJTG
38
38
  brilliance_admin/schema/table/__init__.py,sha256=vuRw8HBuak2LaTZi2dNn5YOrJPalQps-O3Ht-d0AZV4,378
39
39
  brilliance_admin/schema/table/admin_action.py,sha256=0ymRL9DKkBK-AF6wKy7K9R4hkmblh55eHuZA_rjO1Lk,2018
40
40
  brilliance_admin/schema/table/category_table.py,sha256=YNDEabnKkIjqhZ0niVOFqXDFIk0I2H6_FbGgbuO5NZ8,6509
41
- brilliance_admin/schema/table/fields_schema.py,sha256=Tlnxpzb1RgMKLDqFpRD3t6x9lDEAf--hnmzRC3vHZpo,8350
41
+ brilliance_admin/schema/table/fields_schema.py,sha256=E6U0oLREyCU-8HnwNB8Sf40al2bIzgs0-g5fOpqbQkw,8475
42
42
  brilliance_admin/schema/table/table_models.py,sha256=xidraifRYbXGkiVLn6dJ96dkOhW8-22ynE-fbiOjfAU,1018
43
43
  brilliance_admin/schema/table/fields/__init__.py,sha256=RW-sIFTAaSQo4mMR6iWtnefogWPjmg6KAsDwe9mKW1k,291
44
44
  brilliance_admin/schema/table/fields/base.py,sha256=HTOMWjuiTSV7lP1F5huUoit06j8Xd8v82cZ3Qz8Y7TI,9182
@@ -66,8 +66,8 @@ brilliance_admin/static/tinymce/plugins/codesample/css/prism.css,sha256=exAdMtHb
66
66
  brilliance_admin/static/tinymce/plugins/customLink/plugin.js,sha256=illBNpnHDkBsLG6wo_jDPF6z7CGnO1MQWUoDwZKy6vQ,5589
67
67
  brilliance_admin/static/tinymce/plugins/customLink/css/link.css,sha256=gh5nvY8Z92hJfCEBPnIm4jIPCcKKbJnab-30oIfX7Hc,56
68
68
  brilliance_admin/templates/index.html,sha256=T1d7BYLJOmL6eTICyxH82aCStGXq-bom_dJG5aVxfKA,1294
69
- brilliance_admin-0.44.5.dist-info/licenses/LICENSE,sha256=rgWE5Cxk53W0PhTOVmcQedABEWN1QMG-PRz3fz531sE,1074
70
- brilliance_admin-0.44.5.dist-info/METADATA,sha256=hBIeMkKgDKMEgsvtX68QOBGI_lXzW5vAYucMtVhU9Gg,6951
71
- brilliance_admin-0.44.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
- brilliance_admin-0.44.5.dist-info/top_level.txt,sha256=almFFSWrVYieI3i54hYL0fMUaeuIYiazS2Kx4wtK-ns,17
73
- brilliance_admin-0.44.5.dist-info/RECORD,,
69
+ brilliance_admin-0.44.6.dist-info/licenses/LICENSE,sha256=rgWE5Cxk53W0PhTOVmcQedABEWN1QMG-PRz3fz531sE,1074
70
+ brilliance_admin-0.44.6.dist-info/METADATA,sha256=pp645oX-1YAteZF-c67SV2hLYayrxfKNEVd_nMDJDqY,6951
71
+ brilliance_admin-0.44.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
72
+ brilliance_admin-0.44.6.dist-info/top_level.txt,sha256=almFFSWrVYieI3i54hYL0fMUaeuIYiazS2Kx4wtK-ns,17
73
+ brilliance_admin-0.44.6.dist-info/RECORD,,