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/rconfig.py CHANGED
@@ -9,8 +9,7 @@
9
9
  """
10
10
 
11
11
 
12
- from typing import TypedDict, TypeVar
13
- import datetime
12
+ from typing import TypedDict, TypeVar, Generic
14
13
  from datetime import (
15
14
  datetime as Datetime,
16
15
  date as Date,
@@ -21,10 +20,13 @@ from reykit.rbase import Null, throw
21
20
 
22
21
  from . import rdb
23
22
  from .rbase import DatabaseBase
23
+ from .rorm import DatabaseORM as orm
24
24
 
25
25
 
26
26
  __all__ = (
27
+ 'DatabaseConfigSuper',
27
28
  'DatabaseConfig',
29
+ 'DatabaseConfigAsync'
28
30
  )
29
31
 
30
32
 
@@ -32,35 +34,23 @@ type ConfigValue = bool | str | int | float | list | tuple | dict | set | Dateti
32
34
  ConfigRow = TypedDict('ConfigRow', {'key': str, 'value': ConfigValue, 'type': str, 'note': str | None})
33
35
  type ConfigTable = list[ConfigRow]
34
36
  ConfigValueT = TypeVar('T', bound=ConfigValue) # Any.
37
+ DatabaseT = TypeVar('DatabaseT', 'rdb.Database', 'rdb.DatabaseAsync')
35
38
 
36
39
 
37
- class DatabaseConfig(DatabaseBase):
40
+ class DatabaseConfigSuper(DatabaseBase, Generic[DatabaseT]):
38
41
  """
39
- Database config type.
42
+ Database config super type.
40
43
  Can create database used `self.build_db` method.
41
-
42
- Examples
43
- --------
44
- >>> config = DatabaseConfig()
45
- >>> config['key1'] = 1
46
- >>> config['key2', 'note'] = 2
47
- >>> config['key1'], config['key2']
48
- (1, 2)
49
44
  """
50
45
 
51
46
 
52
- def __init__(
53
- self,
54
- db: 'rdb.Database',
55
- db_names: dict[str, str] | None = None
56
- ) -> None:
47
+ def __init__(self, db: DatabaseT) -> None:
57
48
  """
58
49
  Build instance attributes.
59
50
 
60
51
  Parameters
61
52
  ----------
62
53
  db: Database instance.
63
- db_names: Update build database table names.
64
54
  """
65
55
 
66
56
  # Build.
@@ -69,27 +59,25 @@ class DatabaseConfig(DatabaseBase):
69
59
  'config': 'config',
70
60
  'stats_config': 'stats_config'
71
61
  }
72
- if db_names is not None:
73
- self.db_names.update(db_names)
74
62
 
75
63
 
76
- def build_db(self) -> None:
64
+ def handle_build_db(self) -> None:
77
65
  """
78
- Check and build database tables, by `self.db_names`.
66
+ Handle method of check and build database tables, by `self.db_names`.
79
67
  """
80
68
 
81
69
  # Handle parameter.
82
70
 
83
71
  ## Table.
84
- class Config(self.db.orm.Model, table=True):
72
+ class Config(orm.Model, table=True):
85
73
  __name__ = self.db_names['config']
86
- __commment__ = 'Config data table.'
87
- create_time: datetime = self.db.orm.Field(not_null=True, field_default='CURRENT_TIMESTAMP', index_n=True, comment='Config create time.')
88
- update_time: datetime = self.db.orm.Field(field_default='CURRENT_TIMESTAMP', index_n=True, comment='Config update time.')
89
- key = self.db.orm.Field(type=self.db.orm.types.VARCHAR(50), key=True, not_null=True, comment='Config key.')
90
- value = self.db.orm.Field(type=self.db.orm.types.TEXT, not_null=True, comment='Config value.')
91
- type = self.db.orm.Field(type=self.db.orm.types.VARCHAR(50), not_null=True, comment='Config value type.')
92
- note = self.db.orm.Field(type=self.db.orm.types.VARCHAR(500), comment='Config note.')
74
+ __comment__ = 'Config data table.'
75
+ create_time: Datetime = orm.Field(field_default='CURRENT_TIMESTAMP', not_null=True, index_n=True, comment='Config create time.')
76
+ update_time: Datetime = orm.Field(field_default='CURRENT_TIMESTAMP', index_n=True, comment='Config update time.')
77
+ key: str = orm.Field(field_type=orm.types.VARCHAR(50), key=True, not_null=True, comment='Config key.')
78
+ value: str = orm.Field(field_type=orm.types.TEXT, not_null=True, comment='Config value.')
79
+ type: str = orm.Field(field_type=orm.types.VARCHAR(50), not_null=True, comment='Config value type.')
80
+ note: str = orm.Field(field_type=orm.types.VARCHAR(500), comment='Config note.')
93
81
 
94
82
  tables = [Config]
95
83
 
@@ -102,7 +90,7 @@ class DatabaseConfig(DatabaseBase):
102
90
  'name': 'count',
103
91
  'select': (
104
92
  'SELECT COUNT(1)\n'
105
- f'FROM `{self.db_names['base']}`.`{self.db_names['base.config']}`'
93
+ f'FROM `{self.db.database}`.`{self.db_names['config']}`'
106
94
  ),
107
95
  'comment': 'Config count.'
108
96
  },
@@ -110,7 +98,7 @@ class DatabaseConfig(DatabaseBase):
110
98
  'name': 'last_create_time',
111
99
  'select': (
112
100
  'SELECT MAX(`create_time`)\n'
113
- f'FROM `{self.db_names['base']}`.`{self.db_names['base.config']}`'
101
+ f'FROM `{self.db.database}`.`{self.db_names['config']}`'
114
102
  ),
115
103
  'comment': 'Config last record create time.'
116
104
  },
@@ -118,20 +106,44 @@ class DatabaseConfig(DatabaseBase):
118
106
  'name': 'last_update_time',
119
107
  'select': (
120
108
  'SELECT MAX(`update_time`)\n'
121
- f'FROM `{self.db_names['base']}`.`{self.db_names['base.config']}`'
109
+ f'FROM `{self.db.database}`.`{self.db_names['config']}`'
122
110
  ),
123
111
  'comment': 'Config last record update time.'
124
112
  }
125
113
  ]
126
114
  }
127
-
128
115
  ]
129
116
 
117
+ return tables, views_stats
118
+
119
+
120
+ class DatabaseConfig(DatabaseConfigSuper['rdb.Database']):
121
+ """
122
+ Database config type.
123
+ Can create database used `self.build_db` method.
124
+
125
+ Examples
126
+ --------
127
+ >>> config = DatabaseConfig()
128
+ >>> config['key1'] = 1
129
+ >>> config['key2', 'note'] = 2
130
+ >>> config['key1'], config['key2']
131
+ (1, 2)
132
+ """
133
+
134
+
135
+ def build_db(self) -> None:
136
+ """
137
+ Check and build database tables, by `self.db_names`.
138
+ """
139
+
140
+ # Handle parameter.
141
+ tables, views_stats = self.handle_build_db()
142
+
130
143
  # Build.
131
- self.db.build.build(tables=tables, views_stats=views_stats)
144
+ self.db.build.build(tables=tables, views_stats=views_stats, skip=True)
132
145
 
133
146
 
134
- @property
135
147
  def data(self) -> ConfigTable:
136
148
  """
137
149
  Get config data table.
@@ -149,7 +161,7 @@ class DatabaseConfig(DatabaseBase):
149
161
  )
150
162
 
151
163
  # Convert.
152
- global_dict = {'datetime': datetime}
164
+ global_dict = {'datetime': Datetime}
153
165
  result = [
154
166
  {
155
167
  'key': row['key'],
@@ -191,7 +203,7 @@ class DatabaseConfig(DatabaseBase):
191
203
  if value is None:
192
204
  value = default
193
205
  else:
194
- global_dict = {'datetime': datetime}
206
+ global_dict = {'datetime': Datetime}
195
207
  value = eval(value, global_dict)
196
208
 
197
209
  return value
@@ -204,7 +216,7 @@ class DatabaseConfig(DatabaseBase):
204
216
  default_note: str | None = None
205
217
  ) -> ConfigValue | ConfigValueT:
206
218
  """
207
- Set config value.
219
+ Set config default value.
208
220
 
209
221
  Parameters
210
222
  ----------
@@ -316,7 +328,7 @@ class DatabaseConfig(DatabaseBase):
316
328
  )
317
329
 
318
330
  # Convert.
319
- global_dict = {'datetime': datetime}
331
+ global_dict = {'datetime': Datetime}
320
332
  result = result.to_dict('key', 'value')
321
333
  result = {
322
334
  key: eval(value, global_dict)
@@ -342,7 +354,7 @@ class DatabaseConfig(DatabaseBase):
342
354
  )
343
355
 
344
356
  # Convert.
345
- global_dict = {'datetime': datetime}
357
+ global_dict = {'datetime': Datetime}
346
358
  result = [
347
359
  eval(value, global_dict)
348
360
  for value in result
@@ -367,7 +379,7 @@ class DatabaseConfig(DatabaseBase):
367
379
  )
368
380
 
369
381
  # Convert.
370
- global_dict = {'datetime': datetime}
382
+ global_dict = {'datetime': Datetime}
371
383
  result = [
372
384
  eval(value, global_dict)
373
385
  for value in result
@@ -428,3 +440,328 @@ class DatabaseConfig(DatabaseBase):
428
440
  data,
429
441
  'update'
430
442
  )
443
+
444
+
445
+ class DatabaseConfigAsync(DatabaseConfigSuper['rdb.DatabaseAsync']):
446
+ """
447
+ Asynchronous database config type.
448
+ Can create database used `self.build_db` method.
449
+
450
+ Examples
451
+ --------
452
+ >>> config = DatabaseConfig()
453
+ >>> await config['key1'] = 1
454
+ >>> await config['key2', 'note'] = 2
455
+ >>> await config['key1'], config['key2']
456
+ (1, 2)
457
+ """
458
+
459
+
460
+ async def build_db(self) -> None:
461
+ """
462
+ Asynchronous check and build database tables, by `self.db_names`.
463
+ """
464
+
465
+ # Handle parameter.
466
+ tables, views_stats = self.handle_build_db()
467
+
468
+ # Build.
469
+ await self.db.build.build(tables=tables, views_stats=views_stats, skip=True)
470
+
471
+
472
+ async def data(self) -> ConfigTable:
473
+ """
474
+ Asynchronous get config data table.
475
+
476
+ Returns
477
+ -------
478
+ Config data table.
479
+ """
480
+
481
+ # Get.
482
+ result = await self.db.execute.select(
483
+ self.db_names['config'],
484
+ ['key', 'value', 'type', 'note'],
485
+ order='IFNULL(`update_time`, `create_time`) DESC'
486
+ )
487
+
488
+ # Convert.
489
+ global_dict = {'datetime': Datetime}
490
+ result = [
491
+ {
492
+ 'key': row['key'],
493
+ 'value': eval(row['value'], global_dict),
494
+ 'note': row['note']
495
+ }
496
+ for row in result
497
+ ]
498
+
499
+ return result
500
+
501
+
502
+ async def get(self, key: str, default: ConfigValueT | None = None) -> ConfigValue | ConfigValueT:
503
+ """
504
+ Asynchronous get config value, when not exist, then return default value.
505
+
506
+ Parameters
507
+ ----------
508
+ key : Config key.
509
+ default : Config default value.
510
+
511
+ Returns
512
+ -------
513
+ Config value.
514
+ """
515
+
516
+ # Get.
517
+ where = '`key` = :key'
518
+ result = await self.db.execute.select(
519
+ self.db_names['config'],
520
+ '`value`',
521
+ where,
522
+ limit=1,
523
+ key=key
524
+ )
525
+ value = result.scalar()
526
+
527
+ # Default.
528
+ if value is None:
529
+ value = default
530
+ else:
531
+ global_dict = {'datetime': Datetime}
532
+ value = eval(value, global_dict)
533
+
534
+ return value
535
+
536
+
537
+ async def setdefault(
538
+ self,
539
+ key: str,
540
+ default: ConfigValueT | None = None,
541
+ default_note: str | None = None
542
+ ) -> ConfigValue | ConfigValueT:
543
+ """
544
+ Asynchronous set config default value.
545
+
546
+ Parameters
547
+ ----------
548
+ key : Config key.
549
+ default : Config default value.
550
+ default_note : Config default note.
551
+
552
+ Returns
553
+ -------
554
+ Config value.
555
+ """
556
+
557
+ # Set.
558
+ data = {
559
+ 'key': key,
560
+ 'value': repr(default),
561
+ 'type': type(default).__name__,
562
+ 'note': default_note
563
+ }
564
+ result = await self.db.execute.insert(
565
+ self.db_names['config'],
566
+ data,
567
+ 'ignore'
568
+ )
569
+
570
+ # Get.
571
+ if result.rowcount == 0:
572
+ default = await self.get(key)
573
+
574
+ return default
575
+
576
+
577
+ async def update(self, data: dict[str, ConfigValue] | ConfigTable) -> None:
578
+ """
579
+ Asynchronous update config values.
580
+
581
+ Parameters
582
+ ----------
583
+ data : Config update data.
584
+ - `dict[str, Any]`: Config key and value.
585
+ - `ConfigTable`: Config key and value and note.
586
+ """
587
+
588
+ # Handle parameter.
589
+ if type(data) == dict:
590
+ data = [
591
+ {
592
+ 'key': key,
593
+ 'value': repr(value),
594
+ 'type': type(value).__name__
595
+ }
596
+ for key, value in data.items()
597
+ ]
598
+ else:
599
+ data = data.copy()
600
+ for row in data:
601
+ row['value'] = repr(row['value'])
602
+ row['type'] = type(row['value']).__name__
603
+
604
+ # Update.
605
+ await self.db.execute.insert(
606
+ self.db_names['config'],
607
+ data,
608
+ 'update'
609
+ )
610
+
611
+
612
+ async def remove(self, key: str | list[str]) -> None:
613
+ """
614
+ Asynchronous remove config.
615
+
616
+ Parameters
617
+ ----------
618
+ key : Config key or key list.
619
+ """
620
+
621
+ # Remove.
622
+ if type(key) == str:
623
+ where = '`key` = :key'
624
+ limit = 1
625
+ else:
626
+ where = '`key` in :key'
627
+ limit = None
628
+ result = await self.db.execute.delete(
629
+ self.db_names['base.config'],
630
+ where,
631
+ limit=limit,
632
+ key=key
633
+ )
634
+
635
+ # Check.
636
+ if result.rowcount == 0:
637
+ throw(KeyError, key)
638
+
639
+
640
+ async def items(self) -> dict[str, ConfigValue]:
641
+ """
642
+ Asynchronous get all config keys and values.
643
+
644
+ Returns
645
+ -------
646
+ All config keys and values.
647
+ """
648
+
649
+ # Get.
650
+ result = await self.db.execute.select(
651
+ self.db_names['config'],
652
+ ['key', 'value']
653
+ )
654
+
655
+ # Convert.
656
+ global_dict = {'datetime': Datetime}
657
+ result = result.to_dict('key', 'value')
658
+ result = {
659
+ key: eval(value, global_dict)
660
+ for key, value in result.items()
661
+ }
662
+
663
+ return result
664
+
665
+
666
+ async def keys(self) -> list[str]:
667
+ """
668
+ Asynchronous get all config keys.
669
+
670
+ Returns
671
+ -------
672
+ All config keys.
673
+ """
674
+
675
+ # Get.
676
+ result = await self.db.execute.select(
677
+ self.db_names['config'],
678
+ '`key`'
679
+ )
680
+
681
+ # Convert.
682
+ global_dict = {'datetime': Datetime}
683
+ result = [
684
+ eval(value, global_dict)
685
+ for value in result
686
+ ]
687
+
688
+ return result
689
+
690
+
691
+ async def values(self) -> list[ConfigValue]:
692
+ """
693
+ Asynchronous get all config value.
694
+
695
+ Returns
696
+ -------
697
+ All config values.
698
+ """
699
+
700
+ # Get.
701
+ result = await self.db.execute.select(
702
+ self.db_names['config'],
703
+ '`value`'
704
+ )
705
+
706
+ # Convert.
707
+ global_dict = {'datetime': Datetime}
708
+ result = [
709
+ eval(value, global_dict)
710
+ for value in result
711
+ ]
712
+
713
+ return result
714
+
715
+
716
+ async def __getitem__(self, key: str) -> ConfigValue:
717
+ """
718
+ Asynchronous get config value.
719
+
720
+ Parameters
721
+ ----------
722
+ key : Config key.
723
+
724
+ Returns
725
+ -------
726
+ Config value.
727
+ """
728
+
729
+ # Get.
730
+ value = await self.get(key, Null)
731
+
732
+ # Check.
733
+ if value == Null:
734
+ throw(KeyError, key)
735
+
736
+ return value
737
+
738
+
739
+ async def __setitem__(self, key_note: str | tuple[str, str], value: ConfigValue) -> None:
740
+ """
741
+ Asynchronous set config value.
742
+
743
+ Parameters
744
+ ----------
745
+ key_note : Config key and note.
746
+ value : Config value.
747
+ """
748
+
749
+ # Handle parameter.
750
+ if type(key_note) != str:
751
+ key, note = key_note
752
+ else:
753
+ key = key_note
754
+ note = None
755
+
756
+ # Set.
757
+ data = {
758
+ 'key': key,
759
+ 'value': repr(value),
760
+ 'type': type(value).__name__,
761
+ 'note': note
762
+ }
763
+ await self.db.execute.insert(
764
+ self.db_names['config'],
765
+ data,
766
+ 'update'
767
+ )