reydb 1.1.60__py3-none-any.whl → 1.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
reydb/rerror.py CHANGED
@@ -9,29 +9,37 @@
9
9
  """
10
10
 
11
11
 
12
- from typing import Any
12
+ from typing import Any, NoReturn, TypeVar, Generic
13
13
  from collections.abc import Callable
14
+ from inspect import iscoroutinefunction
14
15
  from traceback import StackSummary
15
16
  from functools import wraps as functools_wraps
17
+ from datetime import datetime as Datetime
16
18
  from reykit.rbase import T, Exit, catch_exc
17
19
 
18
20
  from . import rdb
19
21
  from .rbase import DatabaseBase
22
+ from .rorm import DatabaseORM as orm
20
23
 
21
24
 
22
25
  __all__ = (
26
+ 'DatabaseErrorSuper',
23
27
  'DatabaseError',
28
+ 'DatabaseErrorAsync'
24
29
  )
25
30
 
26
31
 
27
- class DatabaseError(DatabaseBase):
32
+ DatabaseT = TypeVar('DatabaseT', 'rdb.Database', 'rdb.DatabaseAsync')
33
+
34
+
35
+ class DatabaseErrorSuper(DatabaseBase, Generic[DatabaseT]):
28
36
  """
29
- Database error type.
37
+ Database error super type.
30
38
  Can create database used `self.build_db` method.
31
39
  """
32
40
 
33
41
 
34
- def __init__(self, db: 'rdb.Database') -> None:
42
+ def __init__(self, db: DatabaseT) -> None:
35
43
  """
36
44
  Build instance attributes.
37
45
 
@@ -42,102 +50,41 @@ class DatabaseError(DatabaseBase):
42
50
 
43
51
  # Build.
44
52
  self.db = db
45
-
46
- ## Database path name.
47
53
  self.db_names = {
48
- 'base': 'base',
49
- 'base.error': 'error',
50
- 'base.stats_error': 'stats_error'
54
+ 'error': 'error',
55
+ 'stats_error': 'stats_error'
51
56
  }
52
57
 
53
58
 
54
- def build_db(self) -> None:
59
+ def handle_build_db(self) -> None:
55
60
  """
56
- Check and build database tables, by `self.db_names`.
61
+ Handle method of check and build database tables, by `self.db_names`.
57
62
  """
58
63
 
59
- # Set parameter.
60
-
61
- ## Database.
62
- databases = [
63
- {
64
- 'name': self.db_names['base']
65
- }
66
- ]
64
+ # Handle parameter.
67
65
 
68
66
  ## Table.
69
- tables = [
70
-
71
- ### 'error'.
72
- {
73
- 'path': (self.db_names['base'], self.db_names['base.error']),
74
- 'fields': [
75
- {
76
- 'name': 'create_time',
77
- 'type': 'datetime',
78
- 'constraint': 'NOT NULL DEFAULT CURRENT_TIMESTAMP',
79
- 'comment': 'Record create time.'
80
- },
81
- {
82
- 'name': 'id',
83
- 'type': 'int unsigned',
84
- 'constraint': 'NOT NULL AUTO_INCREMENT',
85
- 'comment': 'ID.'
86
- },
87
- {
88
- 'name': 'type',
89
- 'type': 'varchar(50)',
90
- 'constraint': 'NOT NULL',
91
- 'comment': 'Error type.'
92
- },
93
- {
94
- 'name': 'data',
95
- 'type': 'json',
96
- 'comment': 'Error data.'
97
- },
98
- {
99
- 'name': 'stack',
100
- 'type': 'json',
101
- 'comment': 'Error code traceback stack.'
102
- },
103
- {
104
- 'name': 'note',
105
- 'type': 'varchar(500)',
106
- 'comment': 'Error note.'
107
- }
108
- ],
109
- 'primary': 'id',
110
- 'indexes': [
111
- {
112
- 'name': 'n_create_time',
113
- 'fields': 'create_time',
114
- 'type': 'noraml',
115
- 'comment': 'Record create time normal index.'
116
- },
117
- {
118
- 'name': 'n_type',
119
- 'fields': 'type',
120
- 'type': 'noraml',
121
- 'comment': 'Error type normal index.'
122
- }
123
- ],
124
- 'comment': 'Error log table.'
125
- },
126
-
127
- ]
67
+ class error(orm.Model, table=True):
68
+ __name__ = self.db_names['error']
69
+ __comment__ = 'Error log table.'
70
+ create_time: Datetime = orm.Field(field_default='CURRENT_TIMESTAMP', not_null=True, index_n=True, comment='Record create time.')
71
+ id: int = orm.Field(field_name='idd', field_type=orm.types_mysql.INTEGER(unsigned=True), key=True, key_auto=True, not_null=True, comment='ID.')
72
+ type: str = orm.Field(field_type=orm.types.VARCHAR(50), not_null=True, index_n=True, comment='Error type.')
73
+ data: str = orm.Field(field_type=orm.types.JSON, comment='Error data.')
74
+ stack: str = orm.Field(field_type=orm.types.JSON, comment='Error code traceback stack.')
75
+ note: str = orm.Field(field_type=orm.types.VARCHAR(500), comment='Error note.')
76
+ tables = [error]
128
77
 
129
78
  ## View stats.
130
79
  views_stats = [
131
-
132
- ### 'stats_error'.
133
80
  {
134
- 'path': (self.db_names['base'], self.db_names['base.stats_error']),
81
+ 'path': self.db_names['stats_error'],
135
82
  'items': [
136
83
  {
137
84
  'name': 'count',
138
85
  'select': (
139
86
  'SELECT COUNT(1)\n'
140
- f'FROM `{self.db_names['base']}`.`{self.db_names['base.error']}`'
87
+ f'FROM `{self.db.database}`.`{self.db_names['error']}`'
141
88
  ),
142
89
  'comment': 'Error log count.'
143
90
  },
@@ -145,7 +92,7 @@ class DatabaseError(DatabaseBase):
145
92
  'name': 'past_day_count',
146
93
  'select': (
147
94
  'SELECT COUNT(1)\n'
148
- f'FROM `{self.db_names['base']}`.`{self.db_names['base.error']}`\n'
95
+ f'FROM `{self.db.database}`.`{self.db_names['error']}`\n'
149
96
  'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) = 0'
150
97
  ),
151
98
  'comment': 'Error log count in the past day.'
@@ -154,7 +101,7 @@ class DatabaseError(DatabaseBase):
154
101
  'name': 'past_week_count',
155
102
  'select': (
156
103
  'SELECT COUNT(1)\n'
157
- f'FROM `{self.db_names['base']}`.`{self.db_names['base.error']}`\n'
104
+ f'FROM `{self.db.database}`.`{self.db_names['error']}`\n'
158
105
  'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) <= 6'
159
106
  ),
160
107
  'comment': 'Error log count in the past week.'
@@ -163,7 +110,7 @@ class DatabaseError(DatabaseBase):
163
110
  'name': 'past_month_count',
164
111
  'select': (
165
112
  'SELECT COUNT(1)\n'
166
- f'FROM `{self.db_names['base']}`.`{self.db_names['base.error']}`\n'
113
+ f'FROM `{self.db.database}`.`{self.db_names['error']}`\n'
167
114
  'WHERE TIMESTAMPDIFF(DAY, `create_time`, NOW()) <= 29'
168
115
  ),
169
116
  'comment': 'Error log count in the past month.'
@@ -172,21 +119,18 @@ class DatabaseError(DatabaseBase):
172
119
  'name': 'last_time',
173
120
  'select': (
174
121
  'SELECT MAX(`create_time`)\n'
175
- f'FROM `{self.db_names['base']}`.`{self.db_names['base.error']}`'
122
+ f'FROM `{self.db.database}`.`{self.db_names['error']}`'
176
123
  ),
177
124
  'comment': 'Error log last record create time.'
178
125
  }
179
126
  ]
180
-
181
127
  }
182
-
183
128
  ]
184
129
 
185
- # Build.
186
- self.db.build.build(databases, tables, views_stats=views_stats)
130
+ return tables, views_stats
187
131
 
188
132
 
189
- def record(
133
+ def handle_record(
190
134
  self,
191
135
  exc: BaseException,
192
136
  stack: StackSummary,
@@ -221,13 +165,87 @@ class DatabaseError(DatabaseBase):
221
165
  'note': note
222
166
  }
223
167
 
168
+ return data
169
+
170
+
171
+ class DatabaseError(DatabaseErrorSuper['rdb.Database']):
172
+ """
173
+ Database error type.
174
+ Can create database used `self.build_db` method.
175
+ """
176
+
177
+
178
+ def build_db(self) -> None:
179
+ """
180
+ Check and build database tables, by `self.db_names`.
181
+ """
182
+
183
+ # Handle parameter.
184
+ tables, views_stats = self.handle_build_db()
185
+
186
+ # Build.
187
+ self.db.build.build(tables=tables, views_stats=views_stats, skip=True)
188
+
189
+
190
+ def record(
191
+ self,
192
+ exc: BaseException,
193
+ stack: StackSummary,
194
+ note: str | None = None
195
+ ) -> None:
196
+ """
197
+ Insert exception information into the table of database.
198
+
199
+ Parameters
200
+ ----------
201
+ exc : Exception instance.
202
+ stack : Exception traceback stack instance.
203
+ note : Exception note.
204
+ """
205
+
206
+ # Handle parameter.
207
+ data = self.handle_record(exc, stack, note)
208
+
224
209
  # Insert.
225
210
  self.db.execute.insert(
226
- self.db_names['base.error'],
211
+ self.db_names['error'],
227
212
  data=data
228
213
  )
229
214
 
230
215
 
216
+ __call__ = record
217
+
218
+
219
+ def record_catch(
220
+ self,
221
+ note: str | None = None,
222
+ filter_type : BaseException | tuple[BaseException, ...] = Exit
223
+ ) -> NoReturn:
224
+ """
225
+ Catch and insert exception information into the table of database and throw exception, must used in except syntax.
226
+
227
+ Parameters
228
+ ----------
229
+ note : Exception note.
230
+ filter_type : Exception types of not insert, but still throw exception.
231
+ """
232
+
233
+ # Handle parameter.
234
+ _, exc, stack = catch_exc()
235
+
236
+ # Filter.
237
+ for type_ in filter_type:
238
+ if isinstance(exc, type_):
239
+ break
240
+
241
+ # Record.
242
+ else:
243
+ self.record(exc, stack, note)
244
+
245
+ # Throw exception.
246
+ raise
247
+
248
+
231
249
  def wrap(
232
250
  self,
233
251
  func: Callable[..., T] | None = None,
@@ -236,13 +254,13 @@ class DatabaseError(DatabaseBase):
236
254
  filter_type : BaseException | tuple[BaseException, ...] = Exit
237
255
  ) -> T | Callable[[Callable[..., T]], Callable[..., T]]:
238
256
  """
239
- Decorator, insert exception information into the table of database, throw exception.
257
+ Decorator, insert exception information into the table of database and throw exception.
240
258
 
241
259
  Parameters
242
260
  ----------
243
261
  func : Function.
244
262
  note : Exception note.
245
- filter_type : Exception type of not inserted, but still throw exception.
263
+ filter_type : Exception types of not insert, but still throw exception.
246
264
 
247
265
  Returns
248
266
  -------
@@ -251,21 +269,21 @@ class DatabaseError(DatabaseBase):
251
269
  Examples
252
270
  --------
253
271
  Method one.
254
- >>> @wrap_error
272
+ >>> @wrap
255
273
  >>> def func(*args, **kwargs): ...
256
274
 
257
275
  Method two.
258
- >>> @wrap_error(**wrap_kwargs)
276
+ >>> @wrap(**wrap_kwargs)
259
277
  >>> def func(*args, **kwargs): ...
260
278
 
261
279
  Method three.
262
280
  >>> def func(*args, **kwargs): ...
263
- >>> func = wrap_error(func, **wrap_kwargs)
281
+ >>> func = wrap(func, **wrap_kwargs)
264
282
 
265
283
  Method four.
266
284
  >>> def func(*args, **kwargs): ...
267
- >>> wrap_error = wrap_error(**wrap_kwargs)
268
- >>> func = wrap_error(func)
285
+ >>> wrap = wrap(**wrap_kwargs)
286
+ >>> func = wrap(func)
269
287
 
270
288
  >>> func(*args, **kwargs)
271
289
  """
@@ -308,18 +326,191 @@ class DatabaseError(DatabaseBase):
308
326
  try:
309
327
  result = func_(*args, **kwargs)
310
328
 
311
- # Log.
329
+ # Record.
312
330
  except BaseException:
313
- _, exc, stack = catch_exc()
331
+ self.record_catch(note, filter_type)
332
+
333
+ return result
334
+
335
+
336
+ return _func
337
+
338
+
339
+ # Decorator.
340
+ if func is None:
341
+ return _wrap
342
+
343
+ # Decorated function.
344
+ else:
345
+ _func = _wrap(func)
346
+ return _func
347
+
348
+
349
+ class DatabaseErrorAsync(DatabaseErrorSuper['rdb.DatabaseAsync']):
350
+ """
351
+ Asynchrouous database error type.
352
+ Can create database used `self.build_db` method.
353
+ """
354
+
355
+
356
+ async def build_db(self) -> None:
357
+ """
358
+ Asynchrouous check and build database tables, by `self.db_names`.
359
+ """
360
+
361
+ # Handle parameter.
362
+ tables, views_stats = self.handle_build_db()
363
+
364
+ # Build.
365
+ await self.db.build.build(tables=tables, views_stats=views_stats, skip=True)
366
+
367
+
368
+ async def record(
369
+ self,
370
+ exc: BaseException,
371
+ stack: StackSummary,
372
+ note: str | None = None
373
+ ) -> None:
374
+ """
375
+ Asynchrouous insert exception information into the table of database.
376
+
377
+ Parameters
378
+ ----------
379
+ exc : Exception instance.
380
+ stack : Exception traceback stack instance.
381
+ note : Exception note.
382
+ """
383
+
384
+ # Handle parameter.
385
+ data = self.handle_record(exc, stack, note)
386
+
387
+ # Insert.
388
+ await self.db.execute.insert(
389
+ self.db_names['error'],
390
+ data=data
391
+ )
392
+
393
+
394
+ __call__ = record
314
395
 
315
- ## Filter.
316
- for type_ in filter_type:
317
- if isinstance(exc, type_):
318
- break
396
+
397
+ async def record_catch(
398
+ self,
399
+ note: str | None = None,
400
+ filter_type : BaseException | tuple[BaseException, ...] = Exit
401
+ ) -> NoReturn:
402
+ """
403
+ Asynchrouous catch and insert exception information into the table of database and throw exception, must used in except syntax.
404
+
405
+ Parameters
406
+ ----------
407
+ note : Exception note.
408
+ filter_type : Exception types of not insert, but still throw exception.
409
+ """
410
+
411
+ # Handle parameter.
412
+ _, exc, stack = catch_exc()
413
+
414
+ # Filter.
415
+ for type_ in filter_type:
416
+ if isinstance(exc, type_):
417
+ break
418
+
419
+ # Record.
420
+ else:
421
+ await self.record(exc, stack, note)
422
+
423
+ # Throw exception.
424
+ raise
425
+
426
+
427
+ def wrap(
428
+ self,
429
+ func: Callable[..., T] | None = None,
430
+ *,
431
+ note: str | None = None,
432
+ filter_type : BaseException | tuple[BaseException, ...] = Exit
433
+ ) -> T | Callable[[Callable[..., T]], Callable[..., T]]:
434
+ """
435
+ Asynchrouous decorator, insert exception information into the table of database, throw exception.
436
+
437
+ Parameters
438
+ ----------
439
+ func : Function.
440
+ note : Exception note.
441
+ filter_type : Exception types of not insert, but still throw exception.
442
+
443
+ Returns
444
+ -------
445
+ Decorated function or decorator with parameter.
446
+
447
+ Examples
448
+ --------
449
+ Method one.
450
+ >>> @wrap
451
+ >>> [async ]def func(*args, **kwargs): ...
452
+
453
+ Method two.
454
+ >>> @wrap(**wrap_kwargs)
455
+ >>> [async ]def func(*args, **kwargs): ...
456
+
457
+ Method three.
458
+ >>> [async ]def func(*args, **kwargs): ...
459
+ >>> func = wrap(func, **wrap_kwargs)
460
+
461
+ Method four.
462
+ >>> [async ]def func(*args, **kwargs): ...
463
+ >>> wrap = wrap(**wrap_kwargs)
464
+ >>> func = wrap(func)
465
+
466
+ Must asynchrouous execute.
467
+ >>> await func(*args, **kwargs)
468
+ """
469
+
470
+ # Handle parameter.
471
+ if issubclass(filter_type, BaseException):
472
+ filter_type = (filter_type,)
473
+
474
+
475
+ def _wrap(func_: Callable[..., T]) -> Callable[..., T]:
476
+ """
477
+ Decorator, insert exception information into the table of database.
478
+
479
+ Parameters
480
+ ----------
481
+ _func : Function.
482
+
483
+ Returns
484
+ -------
485
+ Decorated function.
486
+ """
487
+
488
+
489
+ @functools_wraps(func_)
490
+ async def _func(*args, **kwargs) -> Any:
491
+ """
492
+ Decorated function.
493
+
494
+ Parameters
495
+ ----------
496
+ args : Position arguments of function.
497
+ kwargs : Keyword arguments of function.
498
+
499
+ Returns
500
+ -------
501
+ Function return.
502
+ """
503
+
504
+ # Try execute.
505
+ try:
506
+ if iscoroutinefunction(func_):
507
+ result = await func_(*args, **kwargs)
319
508
  else:
320
- self.record(exc, stack, note)
509
+ result = func_(*args, **kwargs)
321
510
 
322
- raise
511
+ # Record.
512
+ except BaseException:
513
+ await self.record_catch(note, filter_type)
323
514
 
324
515
  return result
325
516
 
@@ -335,5 +526,3 @@ class DatabaseError(DatabaseBase):
335
526
  else:
336
527
  _func = _wrap(func)
337
528
  return _func
338
-
339
- __call__ = record