reydb 1.2.6__py3-none-any.whl → 1.2.8__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/rbuild.py CHANGED
@@ -11,6 +11,7 @@
11
11
 
12
12
  from typing import TypedDict, NotRequired, Literal, Type, TypeVar, Generic
13
13
  from copy import deepcopy
14
+ from sqlalchemy import UniqueConstraint
14
15
  from reykit.rbase import throw, is_instance
15
16
  from reykit.rstdout import ask
16
17
 
@@ -2487,7 +2488,7 @@ class DatabaseBuildSuper(DatabaseBase, Generic[DatabaseT]):
2487
2488
  if column.autoincrement
2488
2489
  else ' | KEY'
2489
2490
  ) + (
2490
- f" | DEFAULT '{column.server_default.arg}'"
2491
+ f" | DEFAULT {column.server_default.arg}"
2491
2492
  if column.server_default
2492
2493
  else ''
2493
2494
  ) + (
@@ -2500,14 +2501,10 @@ class DatabaseBuildSuper(DatabaseBase, Generic[DatabaseT]):
2500
2501
  )
2501
2502
 
2502
2503
  ## Index.
2503
- if (table.indexes):
2504
+ if table.indexes:
2504
2505
  text += '\n' + '\n'.join(
2505
2506
  [
2506
- (
2507
- ' UNIQUE'
2508
- if index.unique
2509
- else ' NORMAL'
2510
- ) + f' INDEX `{index.name}` : ' + ', '.join(
2507
+ ' NORMAL INDEX: ' + ', '.join(
2511
2508
  [
2512
2509
  f'`{column.name}`'
2513
2510
  for column in index.expressions
@@ -2517,6 +2514,24 @@ class DatabaseBuildSuper(DatabaseBase, Generic[DatabaseT]):
2517
2514
  ]
2518
2515
  )
2519
2516
 
2517
+ ## Constraint.
2518
+ if table.constraints:
2519
+ text += '\n' + '\n'.join(
2520
+ [
2521
+ (
2522
+ ' UNIQUE CONSTRAIN: '
2523
+ if type(constraint) == UniqueConstraint
2524
+ else ' PRIMARY KEY CONSTRAIN: '
2525
+ ) + ', '.join(
2526
+ [
2527
+ f'`{column.name}`'
2528
+ for column in constraint.columns
2529
+ ]
2530
+ )
2531
+ for constraint in table.constraints
2532
+ ]
2533
+ )
2534
+
2520
2535
  return text
2521
2536
 
2522
2537
 
reydb/rconfig.py CHANGED
@@ -44,12 +44,12 @@ class DatabaseTableConfig(rorm.Model, table=True):
44
44
  """
45
45
 
46
46
  __comment__ = 'Config data table.'
47
- create_time: rorm.Datetime = rorm.Field(field_default='CURRENT_TIMESTAMP', not_null=True, index_n=True, comment='Config create time.')
48
- update_time: rorm.Datetime = rorm.Field(field_default='ON UPDATE CURRENT_TIMESTAMP', index_n=True, comment='Config update time.')
49
- key: str = rorm.Field(field_type=rorm.types.VARCHAR(50), key=True, comment='Config key.')
50
- value: str = rorm.Field(field_type=rorm.types.TEXT, not_null=True, comment='Config value.')
51
- type: str = rorm.Field(field_type=rorm.types.VARCHAR(50), not_null=True, comment='Config value type.')
52
- note: str = rorm.Field(field_type=rorm.types.VARCHAR(500), comment='Config note.')
47
+ create_time: rorm.Datetime = rorm.Field(field_default=':create_time', not_null=True, index_n=True, comment='Config create time.')
48
+ update_time: rorm.Datetime = rorm.Field(field_default=':update_time', index_n=True, comment='Config update time.')
49
+ key: str = rorm.Field(rorm.types.VARCHAR(50), key=True, comment='Config key.')
50
+ value: str = rorm.Field(rorm.types.TEXT, not_null=True, comment='Config value.')
51
+ type: str = rorm.Field(rorm.types.VARCHAR(50), not_null=True, comment='Config value type.')
52
+ note: str = rorm.Field(rorm.types.VARCHAR(500), comment='Config note.')
53
53
 
54
54
 
55
55
  class DatabaseConfigSuper(DatabaseBase, Generic[DatabaseT]):
reydb/rerror.py CHANGED
@@ -38,12 +38,12 @@ class DatabaseTableError(rorm.Model, table=True):
38
38
  """
39
39
 
40
40
  __comment__ = 'Error log table.'
41
- create_time: rorm.Datetime = rorm.Field(field_default='CURRENT_TIMESTAMP', not_null=True, index_n=True, comment='Record create time.')
42
- id: int = rorm.Field(field_type=rorm.types_mysql.INTEGER(unsigned=True), key_auto=True, comment='ID.')
43
- type: str = rorm.Field(field_type=rorm.types.VARCHAR(50), not_null=True, index_n=True, comment='Error type.')
44
- data: str = rorm.Field(field_type=rorm.types.JSON, comment='Error data.')
45
- stack: str = rorm.Field(field_type=rorm.types.JSON, comment='Error code traceback stack.')
46
- note: str = rorm.Field(field_type=rorm.types.VARCHAR(500), comment='Error note.')
41
+ create_time: rorm.Datetime = rorm.Field(field_default=':create_time', not_null=True, index_n=True, comment='Record create time.')
42
+ id: int = rorm.Field(rorm.types_mysql.INTEGER(unsigned=True), key_auto=True, comment='ID.')
43
+ type: str = rorm.Field(rorm.types.VARCHAR(50), not_null=True, index_n=True, comment='Error type.')
44
+ data: str = rorm.Field(rorm.types.JSON, comment='Error data.')
45
+ stack: str = rorm.Field(rorm.types.JSON, comment='Error code traceback stack.')
46
+ note: str = rorm.Field(rorm.types.VARCHAR(500), comment='Error note.')
47
47
 
48
48
 
49
49
  class DatabaseErrorSuper(DatabaseBase, Generic[DatabaseT]):
reydb/rorm.py CHANGED
@@ -21,12 +21,13 @@ from sqlalchemy import types
21
21
  from sqlalchemy.dialects.mysql import types as types_mysql
22
22
  from sqlalchemy.sql.sqltypes import TypeEngine
23
23
  from sqlalchemy.sql.dml import Insert, Update, Delete
24
+ from sqlalchemy.sql import func as sqlalchemy_func
24
25
  from sqlmodel import SQLModel, Session, Table
25
26
  from sqlmodel.ext.asyncio.session import AsyncSession
26
27
  from sqlmodel.main import SQLModelMetaclass, FieldInfo, default_registry
27
28
  from sqlmodel.sql._expression_select_cls import SelectOfScalar as Select
28
29
  from datetime import datetime, date, time, timedelta
29
- from reykit.rbase import CallableT, Null, throw, is_instance
30
+ from reykit.rbase import CallableT, throw, is_instance
30
31
 
31
32
  from . import rdb
32
33
  from .rbase import (
@@ -122,14 +123,18 @@ class DatabaseORMModelMeta(DatabaseORMBase, SQLModelMetaclass):
122
123
  table_args['comment'] = attrs.pop('__comment__')
123
124
 
124
125
  ## Field.
125
- for __name__ in attrs['__annotations__']:
126
- field = attrs.get(__name__)
127
- if field is None:
128
- field = attrs[__name__] = DatabaseORMModelField()
126
+ for attr_name in attrs['__annotations__']:
127
+ attr_name: str
128
+ if attr_name in attrs:
129
+ field = attrs[attr_name]
130
+ if type(field) != DatabaseORMModelField:
131
+ field = attrs[attr_name] = DatabaseORMModelField(field)
132
+ else:
133
+ field = attrs[attr_name] = DatabaseORMModelField()
129
134
  sa_column_kwargs: dict = field.sa_column_kwargs
130
- sa_column_kwargs.setdefault('name', __name__)
135
+ sa_column_kwargs.setdefault('name', attr_name)
131
136
 
132
- ## Unique.
137
+ ## Replace.
133
138
  table = default_registry.metadata.tables.get(table_name)
134
139
  if table is not None:
135
140
  default_registry.metadata.remove(table)
@@ -155,11 +160,13 @@ class DatabaseORMModelMeta(DatabaseORMBase, SQLModelMetaclass):
155
160
  super().__init__(name, bases, attrs, **kwargs)
156
161
 
157
162
  # Set parameter.
158
- if '__annotations__' in attrs:
163
+ if (
164
+ '__annotations__' in attrs
165
+ and hasattr(cls, '__table__')
166
+ ):
159
167
  table: Table = cls.__table__
160
168
  for index in table.indexes:
161
- index_name_prefix = ['u_', 'n_'][index.unique]
162
- index_name = index_name_prefix + '_'.join(
169
+ index_name = '_'.join(
163
170
  column.key
164
171
  for column in index.expressions
165
172
  )
@@ -180,12 +187,12 @@ class DatabaseORMModelField(DatabaseORMBase, FieldInfo):
180
187
  @overload
181
188
  def __init__(
182
189
  self,
183
- arg_default: Any | Callable[[], Any] | Null = Null,
184
- *,
185
- arg_name: str | None = None,
186
- field_default: str | Literal['CURRENT_TIMESTAMP'] | Literal['ON UPDATE CURRENT_TIMESTAMP'] | None = None,
187
- filed_name: str | None = None,
188
190
  field_type: TypeEngine | None = None,
191
+ *,
192
+ field_default: str | Literal[':time'] | Literal[':create_time'] | Literal[':update_time'] = None,
193
+ arg_default: Any | Callable[[], Any] | None = None,
194
+ arg_update: Any | Callable[[], Any] = None,
195
+ name: str | None = None,
189
196
  key: bool = False,
190
197
  key_auto: bool = False,
191
198
  not_null: bool = False,
@@ -208,7 +215,7 @@ class DatabaseORMModelField(DatabaseORMBase, FieldInfo):
208
215
 
209
216
  def __init__(
210
217
  self,
211
- arg_default: Any | Callable[[], Any] | Null = Null,
218
+ field_type: TypeEngine | None = None,
212
219
  **kwargs: Any
213
220
  ) -> None:
214
221
  """
@@ -216,19 +223,22 @@ class DatabaseORMModelField(DatabaseORMBase, FieldInfo):
216
223
 
217
224
  Parameters
218
225
  ----------
219
- arg_default : Call argument default value.
220
- arg_name : Call argument name.
221
- - `None`: Same as attribute name.
222
- field_default : Database field defualt value.
223
- - `Literal['current_timestamp']`: Set SQL syntax 'current_timestamp', case insensitive.
224
- - `Literal['on update current_timestamp']`: Set SQL syntax 'on update current_timestamp', case insensitive.
225
- field_name : Database field name.
226
- - `None`: Same as attribute name.
227
226
  field_type : Database field type.
228
227
  - `None`: Based type annotation automatic judgment.
228
+ field_default : Database field defualt value.
229
+ - `Literal[':time']`: Set SQL syntax 'DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'.
230
+ - `Literal[':create_time']`: Set SQL syntax 'DEFAULT CURRENT_TIMESTAMP'.
231
+ - `Literal[':update_time']`: Set SQL syntax 'ON UPDATE CURRENT_TIMESTAMP'.
232
+ arg_default : Call argument default value.
233
+ - `Callable[[], Any]`: Call function and use return value.
234
+ arg_update : In `Session` management, When commit update record, then default value is this value.
235
+ - `Callable[[], Any]`: Call function and use return value.
236
+ name : Call argument name and database field name.
237
+ - `None`: Same as attribute name.
229
238
  key : Whether the field is primary key.
230
- key_auto : Whether the field is automatic increment primary key.
239
+ key_auto : Whether the field is primary key and automatic increment.
231
240
  not_null : Whether the field is not null constraint.
241
+ - `Litreal[False]`: When argument `arg_default` is `Null`, then set argument `arg_default` is `None`.
232
242
  index_n : Whether the field add normal index.
233
243
  index_u : Whether the field add unique index.
234
244
  comment : Field commment.
@@ -257,7 +267,6 @@ class DatabaseORMModelField(DatabaseORMBase, FieldInfo):
257
267
 
258
268
  ## Convert argument name.
259
269
  mapping_keys = {
260
- 'arg_name': 'alias',
261
270
  'key': 'primary_key',
262
271
  'index_n': 'index',
263
272
  'index_u': 'unique',
@@ -272,7 +281,6 @@ class DatabaseORMModelField(DatabaseORMBase, FieldInfo):
272
281
  'num_places': 'max_digits',
273
282
  'num_places_dec': 'decimal_places'
274
283
  }
275
-
276
284
  for key_old, key_new in mapping_keys.items():
277
285
  if type(key_new) != tuple:
278
286
  key_new = (key_new,)
@@ -281,30 +289,13 @@ class DatabaseORMModelField(DatabaseORMBase, FieldInfo):
281
289
  for key in key_new:
282
290
  kwargs[key] = value
283
291
 
284
- ## Argument default.
285
- if (
286
- arg_default != Null
287
- and callable(arg_default)
288
- ):
289
- kwargs['default_factory'] = arg_default
290
- else:
291
- kwargs['default'] = arg_default
292
-
293
- ## Field default.
294
- if 'field_default' in kwargs:
295
- field_default: str = kwargs.pop('field_default')
296
- field_default_upper = field_default.upper()
297
- if field_default_upper in ('CURRENT_TIMESTAMP', 'ON UPDATE CURRENT_TIMESTAMP'):
298
- field_default = sqlalchemy_text(field_default_upper)
299
- kwargs['sa_column_kwargs']['server_default'] = field_default
300
-
301
- ## Field name.
302
- if 'field_name' in kwargs:
303
- kwargs['sa_column_kwargs']['name'] = kwargs.pop('field_name')
304
-
305
292
  ## Field type.
306
- if 'field_type' in kwargs:
307
- kwargs['sa_type'] = kwargs.pop('field_type')
293
+ if field_type is not None:
294
+ kwargs['sa_type'] = field_type
295
+
296
+ ## Name.
297
+ if 'name' in kwargs:
298
+ kwargs['alias'] = kwargs['sa_column_kwargs']['name'] = kwargs.pop('field_name')
308
299
 
309
300
  ## Key auto.
310
301
  if kwargs.get('key_auto'):
@@ -313,12 +304,45 @@ class DatabaseORMModelField(DatabaseORMBase, FieldInfo):
313
304
  else:
314
305
  kwargs['sa_column_kwargs']['autoincrement'] = False
315
306
 
307
+ ## Key.
308
+ if kwargs.get('primary_key'):
309
+ kwargs['nullable'] = False
310
+
316
311
  ## Non null.
317
312
  if 'not_null' in kwargs:
318
313
  kwargs['nullable'] = not kwargs.pop('not_null')
319
314
  else:
320
315
  kwargs['nullable'] = True
321
316
 
317
+ ## Field default.
318
+ if 'field_default' in kwargs:
319
+ field_default: str = kwargs.pop('field_default')
320
+ if field_default == ':time':
321
+ field_default = sqlalchemy_text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP')
322
+ if field_default == ':create_time':
323
+ field_default = sqlalchemy_text('CURRENT_TIMESTAMP')
324
+ elif field_default == ':update_time':
325
+ if kwargs['nullable']:
326
+ field_default = sqlalchemy_text('NULL ON UPDATE CURRENT_TIMESTAMP')
327
+ else:
328
+ field_default = sqlalchemy_text('NOT NULL ON UPDATE CURRENT_TIMESTAMP')
329
+ kwargs['sa_column_kwargs']['server_default'] = field_default
330
+
331
+ ## Argument default.
332
+ arg_default = kwargs.pop('arg_default', None)
333
+ if arg_default is not None:
334
+ if callable(arg_default):
335
+ kwargs['default_factory'] = arg_default
336
+ else:
337
+ kwargs['default'] = arg_default
338
+ elif kwargs['nullable']:
339
+ kwargs['default'] = None
340
+
341
+ ## Argument update.
342
+ if 'arg_update' in kwargs:
343
+ arg_update = kwargs.pop('arg_update')
344
+ kwargs['sa_column_kwargs']['onupdate'] = arg_update
345
+
322
346
  ## Comment.
323
347
  if 'comment' in kwargs:
324
348
  kwargs['sa_column_kwargs']['comment'] = kwargs.pop('comment')
@@ -1646,6 +1670,9 @@ types = types
1646
1670
  ## Database ORM model MySQL filed types.
1647
1671
  types_mysql = types_mysql
1648
1672
 
1673
+ ## Database ORM model functions.
1674
+ funcs = sqlalchemy_func
1675
+
1649
1676
  ## Create decorator of validate database ORM model.
1650
1677
  wrap_validate_model = pydantic_model_validator
1651
1678
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reydb
3
- Version: 1.2.6
3
+ Version: 1.2.8
4
4
  Summary: Database method set.
5
5
  Project-URL: homepage, https://github.com/reyxbo/reydb/
6
6
  Author-email: Rey <reyxbo@163.com>
@@ -1,15 +1,15 @@
1
1
  reydb/__init__.py,sha256=4mnlkfJfkBfxBpCotVUJ86f4AnT8plqlFbGiH3vZ4PM,550
2
2
  reydb/rall.py,sha256=IxSPGh77xz7ndDC7J8kZ_66Gq_xTAztGtnELUku1Ouw,364
3
3
  reydb/rbase.py,sha256=vx37yV6LlWP89nWAfYyOf0Xm3N_e9eB8z5Mxe-aTEo4,8248
4
- reydb/rbuild.py,sha256=imakdlqQXzQlbAukti3_REVU_h7IRRE3fwUk91LaIIM,80430
5
- reydb/rconfig.py,sha256=JvNf9LU6CzD9eThM8BZz0EVJeDgALmX8JHpY_mXR5mg,19207
4
+ reydb/rbuild.py,sha256=0jI0MNl-BIhQtuT_-GeXBPTjG76k9EE3wwEQXGhTJyc,80938
5
+ reydb/rconfig.py,sha256=B_lwfmMg4V4C_SmuLZi8dqGhb3El3ahxouj1snhS_Ek,19143
6
6
  reydb/rconn.py,sha256=guRaR8N6RuzZzujwaeq7HhKWTizF9SrUBqEAFjfjpoo,6909
7
7
  reydb/rdb.py,sha256=syyqZbEu92NbCj9O6_T6iAv7E46CyfQOC4T8qtPfHNs,14364
8
- reydb/rerror.py,sha256=Cmbcz5CgpI2ro7CbFHUYWP6zuiFJoxy_ENzSUNuuwe8,14924
8
+ reydb/rerror.py,sha256=Hqb2CA6sG7yEPDt3UHzqrgdt63BqoWbCzji3mKBIlp0,14864
9
9
  reydb/rexec.py,sha256=djHx311c6mr1IjzNLqnGe-4yr3qNmYGUy4pHQA3WElQ,53042
10
10
  reydb/rinfo.py,sha256=LjrqTA7JJbWJsjXwV-zKpbE1htv-whg6239hoQj4yIU,18151
11
- reydb/rorm.py,sha256=baHqpNqnBaE1qQpsc5TaegJBbOhWnl748rPPzO7Ab6Q,42314
12
- reydb-1.2.6.dist-info/METADATA,sha256=O94lfy2GvYZTAHXYwRlts15238S9IqTmoTIyDiwmJyo,1621
13
- reydb-1.2.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
- reydb-1.2.6.dist-info/licenses/LICENSE,sha256=UYLPqp7BvPiH8yEZduJqmmyEl6hlM3lKrFIefiD4rvk,1059
15
- reydb-1.2.6.dist-info/RECORD,,
11
+ reydb/rorm.py,sha256=BXRmAaZRrIS6ZprtKRDMUHXtxuaMa6RNC7-_uqARSpo,43650
12
+ reydb-1.2.8.dist-info/METADATA,sha256=LW49lxiggNPo5NgnLVeKo1Euvi11f3QlrD40falMIOE,1621
13
+ reydb-1.2.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
+ reydb-1.2.8.dist-info/licenses/LICENSE,sha256=UYLPqp7BvPiH8yEZduJqmmyEl6hlM3lKrFIefiD4rvk,1059
15
+ reydb-1.2.8.dist-info/RECORD,,
File without changes