encommon 0.22.9__py3-none-any.whl → 0.22.10__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.
encommon/times/windows.py CHANGED
@@ -8,8 +8,13 @@ is permitted, for more information consult the project license file.
8
8
 
9
9
 
10
10
  from copy import deepcopy
11
+ from threading import Lock
12
+ from typing import Annotated
11
13
  from typing import Optional
12
14
  from typing import TYPE_CHECKING
15
+ from typing import Type
16
+
17
+ from pydantic import Field
13
18
 
14
19
  from sqlalchemy import Column
15
20
  from sqlalchemy import String
@@ -23,6 +28,8 @@ from .common import PARSABLE
23
28
  from .params import WindowsParams
24
29
  from .time import Time
25
30
  from .window import Window
31
+ from ..types import BaseModel
32
+ from ..types import DictStrAny
26
33
 
27
34
  if TYPE_CHECKING:
28
35
  from .params import WindowParams
@@ -33,17 +40,7 @@ WINDOWS = dict[str, Window]
33
40
 
34
41
 
35
42
 
36
- class SQLBase(DeclarativeBase):
37
- """
38
- Some additional class that SQLAlchemy requires to work.
39
-
40
- .. note::
41
- Input parameters are not defined, check parent class.
42
- """
43
-
44
-
45
-
46
- class WindowsTable(SQLBase):
43
+ class WindowsTable(DeclarativeBase):
47
44
  """
48
45
  Schematic for the database operations using SQLAlchemy.
49
46
 
@@ -73,7 +70,83 @@ class WindowsTable(SQLBase):
73
70
  String,
74
71
  nullable=False)
75
72
 
76
- __tablename__ = 'windows'
73
+
74
+
75
+ class WindowsRecord(BaseModel):
76
+ """
77
+ Contain the information of the record from the database.
78
+
79
+ :param record: Record from the SQLAlchemy query routine.
80
+ """
81
+
82
+ group: Annotated[
83
+ str,
84
+ Field(...,
85
+ description='Group the children by category',
86
+ min_length=1)]
87
+
88
+ unique: Annotated[
89
+ str,
90
+ Field(...,
91
+ description='Unique identifier for the child',
92
+ min_length=1)]
93
+
94
+ last: Annotated[
95
+ str,
96
+ Field(...,
97
+ description='Last schedule for the period',
98
+ min_length=20,
99
+ max_length=32)]
100
+
101
+ next: Annotated[
102
+ str,
103
+ Field(...,
104
+ description='Next schedule for the period',
105
+ min_length=20,
106
+ max_length=32)]
107
+
108
+ update: Annotated[
109
+ str,
110
+ Field(...,
111
+ description='When the record was updated',
112
+ min_length=20,
113
+ max_length=32)]
114
+
115
+
116
+ def __init__(
117
+ self,
118
+ record: Optional[DeclarativeBase] = None,
119
+ ) -> None:
120
+ """
121
+ Initialize instance for class using provided parameters.
122
+ """
123
+
124
+ fields = [
125
+ 'group',
126
+ 'unique',
127
+ 'last',
128
+ 'next',
129
+ 'update']
130
+
131
+ params = {
132
+ x: getattr(record, x)
133
+ for x in fields}
134
+
135
+
136
+ timefs = [
137
+ 'last',
138
+ 'next',
139
+ 'update']
140
+
141
+ params |= {
142
+ k: (Time(v).simple
143
+ if v else None)
144
+ for k, v in
145
+ params.items()
146
+ if k in timefs}
147
+
148
+
149
+ super().__init__(**params)
77
150
 
78
151
 
79
152
 
@@ -108,6 +181,8 @@ class Windows:
108
181
 
109
182
  __store: str
110
183
  __group: str
184
+ __table: Type[WindowsTable]
185
+ __locker: Lock
111
186
 
112
187
  __sengine: Engine
113
188
  __session: (
@@ -117,16 +192,17 @@ class Windows:
117
192
  __start: Time
118
193
  __stop: Time
119
194
 
120
- __windows: WINDOWS
195
+ __childs: WINDOWS
121
196
 
122
197
 
123
- def __init__(
198
+ def __init__( # noqa: CFQ002
124
199
  self,
125
200
  params: Optional['WindowsParams'] = None,
126
201
  start: PARSABLE = 'now',
127
202
  stop: PARSABLE = '3000-01-01',
128
203
  *,
129
204
  store: str = 'sqlite:///:memory:',
205
+ table: str = 'windows',
130
206
  group: str = 'default',
131
207
  ) -> None:
132
208
  """
@@ -144,7 +220,17 @@ class Windows:
144
220
  self.__store = store
145
221
  self.__group = group
146
222
 
147
- self.__make_engine()
223
+ class SQLBase(DeclarativeBase):
224
+ pass
225
+
226
+ self.__table = type(
227
+ f'encommon_windows_{table}',
228
+ (SQLBase, WindowsTable),
229
+ {'__tablename__': table})
230
+
231
+ self.__locker = Lock()
232
+
233
+ self.__build_engine()
148
234
 
149
235
 
150
236
  start = Time(start)
@@ -156,12 +242,12 @@ class Windows:
156
242
  self.__stop = stop
157
243
 
158
244
 
159
- self.__windows = {}
245
+ self.__childs = {}
160
246
 
161
- self.load_children()
247
+ self.__build_objects()
162
248
 
163
249
 
164
- def __make_engine(
250
+ def __build_engine(
165
251
  self,
166
252
  ) -> None:
167
253
  """
@@ -172,7 +258,7 @@ class Windows:
172
258
  self.__store,
173
259
  pool_pre_ping=True)
174
260
 
175
- (SQLBase.metadata
261
+ (self.__table.metadata
176
262
  .create_all(sengine))
177
263
 
178
264
  session = (
@@ -182,6 +268,23 @@ class Windows:
182
268
  self.__session = session
183
269
 
184
270
 
271
+ def __build_objects(
272
+ self,
273
+ ) -> None:
274
+ """
275
+ Construct instances using the configuration parameters.
276
+ """
277
+
278
+ params = self.__params
279
+
280
+ items = (
281
+ params.windows
282
+ .items())
283
+
284
+ for name, item in items:
285
+ self.create(name, item)
286
+
287
+
185
288
  @property
186
289
  def params(
187
290
  self,
@@ -221,6 +324,19 @@ class Windows:
221
324
  return self.__group
222
325
 
223
326
 
327
+ @property
328
+ def store_table(
329
+ self,
330
+ ) -> Type[WindowsTable]:
331
+ """
332
+ Return the value for the attribute from class instance.
333
+
334
+ :returns: Value for the attribute from class instance.
335
+ """
336
+
337
+ return self.__table
338
+
339
+
224
340
  @property
225
341
  def store_engine(
226
342
  self,
@@ -283,124 +399,55 @@ class Windows:
283
399
  :returns: Value for the attribute from class instance.
284
400
  """
285
401
 
286
- return dict(self.__windows)
402
+ return dict(self.__childs)
287
403
 
288
404
 
289
- def load_children(
405
+ def save_children(
290
406
  self,
291
407
  ) -> None:
292
408
  """
293
- Construct the children instances for the primary class.
409
+ Save the child caches from the attribute into database.
294
410
  """
295
411
 
296
- params = self.__params
297
- windows = self.__windows
298
-
299
- start = self.__start
300
- stop = self.__stop
412
+ sess = self.__session()
413
+ lock = self.__locker
301
414
 
415
+ table = self.__table
302
416
  group = self.__group
417
+ childs = self.__childs
303
418
 
304
- session = self.store_session
305
-
306
- config = params.windows
307
-
308
-
309
- _table = WindowsTable
310
- _group = _table.group
311
- _unique = _table.unique
312
-
313
- query = (
314
- session.query(_table)
315
- .filter(_group == group)
316
- .order_by(_unique))
317
-
318
- for record in query.all():
319
-
320
- unique = str(record.unique)
321
- next = str(record.next)
322
-
323
- if unique not in config:
324
- continue
325
419
 
326
- _config = config[unique]
420
+ inserts: list[DictStrAny] = []
327
421
 
328
- _config.start = next
329
- _config.anchor = next
422
+ update = Time('now')
330
423
 
331
424
 
332
- items = config.items()
425
+ items = childs.items()
333
426
 
334
- for key, value in items:
427
+ for unique, cache in items:
335
428
 
336
- if key in windows:
429
+ _last = cache.last.subsec
430
+ _next = cache.next.subsec
431
+ _update = update.subsec
337
432
 
338
- window = windows[key]
433
+ inputs: DictStrAny = {
434
+ 'group': group,
435
+ 'unique': unique,
436
+ 'last': _last,
437
+ 'next': _next,
438
+ 'update': _update}
339
439
 
340
- window.update(value.start)
440
+ inserts.append(inputs)
341
441
 
342
- continue
343
442
 
344
- _start = (
345
- value.start or start)
443
+ with lock, sess as session:
346
444
 
347
- _stop = (
348
- value.stop or stop)
445
+ for insert in inserts:
349
446
 
350
- if _start < start:
351
- _start = start
447
+ session.merge(
448
+ table(**insert))
352
449
 
353
- if _stop > stop:
354
- _stop = stop
355
-
356
- _anchor = (
357
- value.anchor or _start)
358
-
359
- window = Window(
360
- value.window,
361
- start=_start,
362
- stop=_stop,
363
- anchor=_anchor,
364
- delay=value.delay)
365
-
366
- windows[key] = window
367
-
368
-
369
- self.__windows = windows
370
-
371
-
372
- def save_children(
373
- self,
374
- ) -> None:
375
- """
376
- Save the child caches from the attribute into database.
377
- """
378
-
379
- windows = self.__windows
380
-
381
- group = self.__group
382
-
383
- session = self.store_session
384
-
385
-
386
- items = windows.items()
387
-
388
- for unique, window in items:
389
-
390
- update = Time('now')
391
-
392
- append = WindowsTable(
393
- group=group,
394
- unique=unique,
395
- last=window.last.subsec,
396
- next=window.next.subsec,
397
- update=update.subsec)
398
-
399
- session.merge(append)
400
-
401
-
402
- session.commit()
403
- session.close()
450
+ session.commit()
404
451
 
405
452
 
406
453
  def ready(
@@ -416,14 +463,14 @@ class Windows:
416
463
  :returns: Boolean indicating whether enough time passed.
417
464
  """
418
465
 
419
- windows = self.__windows
466
+ childs = self.__childs
420
467
 
421
- if unique not in windows:
468
+ if unique not in childs:
422
469
  raise ValueError('unique')
423
470
 
424
- window = windows[unique]
471
+ child = childs[unique]
425
472
 
426
- ready = window.ready(update)
473
+ ready = child.ready(update)
427
474
 
428
475
  if ready is True:
429
476
  self.save_children()
@@ -448,6 +495,52 @@ class Windows:
448
495
  unique, update)
449
496
 
450
497
 
498
+ def select(
499
+ self,
500
+ unique: str,
501
+ ) -> Optional[WindowsRecord]:
502
+ """
503
+ Return the record from within the table in the database.
504
+
505
+ :returns: Record from within the table in the database.
506
+ """
507
+
508
+ sess = self.__session()
509
+ lock = self.__locker
510
+
511
+ table = self.__table
512
+ model = WindowsRecord
513
+
514
+ table = self.__table
515
+ group = self.__group
516
+
517
+ _unique = table.unique
518
+ _group = table.group
519
+
520
+
521
+ with lock, sess as session:
522
+
523
+ query = (
524
+ session.query(table)
525
+ .filter(_unique == unique)
526
+ .filter(_group == group))
527
+
528
+ _records = list(query.all())
529
+
530
+
531
+ records = [
532
+ model(x)
533
+ for x in _records]
534
+
535
+
536
+ if len(records) == 0:
537
+ return None
538
+
539
+ assert len(records) == 1
540
+
541
+ return records[0]
542
+
543
+
451
544
  def create(
452
545
  self,
453
546
  unique: str,
@@ -461,20 +554,58 @@ class Windows:
461
554
  :returns: Newly constructed instance of related class.
462
555
  """
463
556
 
464
- config = (
465
- self.params
466
- .windows)
557
+ childs = self.__childs
558
+ _start = self.__start
559
+ _stop = self.__stop
467
560
 
468
- if unique in config:
561
+ if unique in childs:
469
562
  raise ValueError('unique')
470
563
 
471
- config[unique] = params
564
+ window = params.window
565
+ start = params.start
566
+ stop = params.stop
567
+ anchor = params.anchor
568
+ delay = params.delay
569
+
570
+
571
+ select = self.select(unique)
572
+
573
+ if select is not None:
574
+ start = select.next
575
+ anchor = select.next
576
+
577
+
578
+ child_start = Time(
579
+ start if start
580
+ else _start)
581
+
582
+ child_stop = Time(
583
+ stop if stop
584
+ else _stop)
585
+
586
+ anchor = anchor or start
587
+
588
+
589
+ if child_start < _start:
590
+ child_start = _start
591
+
592
+ if child_stop > _stop:
593
+ child_stop = _stop
594
+
595
+
596
+ child = Window(
597
+ window=window,
598
+ start=child_start,
599
+ stop=child_stop,
600
+ anchor=anchor,
601
+ delay=delay)
602
+
603
+ childs[unique] = child
472
604
 
473
- self.load_children()
474
605
 
475
606
  self.save_children()
476
607
 
477
- return self.children[unique]
608
+ return child
478
609
 
479
610
 
480
611
  def update(
@@ -489,14 +620,14 @@ class Windows:
489
620
  :param value: Override the time updated for window value.
490
621
  """
491
622
 
492
- windows = self.__windows
623
+ childs = self.__childs
493
624
 
494
- if unique not in windows:
625
+ if unique not in childs:
495
626
  raise ValueError('unique')
496
627
 
497
- window = windows[unique]
628
+ child = childs[unique]
498
629
 
499
- window.update(value)
630
+ child.update(value)
500
631
 
501
632
  self.save_children()
502
633
 
@@ -515,32 +646,26 @@ class Windows:
515
646
  :param unique: Unique identifier for the related child.
516
647
  """
517
648
 
518
- params = self.__params
519
- windows = self.__windows
649
+ sess = self.__session()
650
+ lock = self.__locker
651
+ childs = self.__childs
520
652
 
653
+ table = self.__table
521
654
  group = self.__group
522
655
 
523
- session = self.store_session
524
-
525
- config = params.windows
526
-
527
-
528
- if unique in config:
529
- del config[unique]
656
+ _unique = table.unique
657
+ _group = table.group
530
658
 
531
- if unique in windows:
532
- del windows[unique]
533
659
 
660
+ with lock, sess as session:
534
661
 
535
- _table = WindowsTable
536
- _group = _table.group
537
- _unique = _table.unique
662
+ (session.query(table)
663
+ .filter(_unique == unique)
664
+ .filter(_group == group)
665
+ .delete())
538
666
 
539
- (session.query(_table)
540
- .filter(_unique == unique)
541
- .filter(_group == group)
542
- .delete())
667
+ session.commit()
543
668
 
544
669
 
545
- session.commit()
546
- session.close()
670
+ if unique in childs:
671
+ del childs[unique]
encommon/version.txt CHANGED
@@ -1 +1 @@
1
- 0.22.9
1
+ 0.22.10
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: encommon
3
- Version: 0.22.9
3
+ Version: 0.22.10
4
4
  Summary: Enasis Network Common Library
5
5
  License: MIT
6
6
  Project-URL: Source, https://github.com/enasisnetwork/encommon
@@ -1,7 +1,7 @@
1
1
  encommon/__init__.py,sha256=YDGzuhpk5Gd1hq54LI0hw1NrrDvrJDrvH20TEy_0l5E,443
2
2
  encommon/conftest.py,sha256=I7Zl2cMytnA-mwSPh0rRjsU0YSlES94jQq6mocRhVUE,1884
3
3
  encommon/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- encommon/version.txt,sha256=hPPb5ICPp3yDJEOvgKXU-rypzwckbQ9Hysmp56lDQF4,7
4
+ encommon/version.txt,sha256=Wq9IWpzuJ4CrvFmxsUki3zG6ICOaWS0zYSOJ3mERGuo,8
5
5
  encommon/colors/__init__.py,sha256=XRiGimMj8oo040NO5a5ZsbsIUxaGVW4tf4xWTPWgnZY,269
6
6
  encommon/colors/color.py,sha256=vdOqOsJYJcrGq0b4udegrn4E8gcuVGx6iTRg3_s8Z-Q,11798
7
7
  encommon/colors/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
@@ -36,25 +36,25 @@ encommon/times/__init__.py,sha256=QX4iuZ59UlsMbEWbubnVJXJtrOubNxAAAv510urcLUA,97
36
36
  encommon/times/common.py,sha256=tLlQUKU-KMrf1Dy_9qgg2J-8ytVpyqPs5ZXV9_TlvVk,1036
37
37
  encommon/times/duration.py,sha256=ffmzBHGZvUucactH6yjUZGrvG6VEuAgMUgdvuEkKMhU,10785
38
38
  encommon/times/params.py,sha256=qg0mLkXVsl54m72kd9uXRvmYKqUR_Ag5PBfnTsrwQhE,4360
39
- encommon/times/parse.py,sha256=_PF12z-UOa75SyeUpBXVn7Jjt-c-Pfnzt6pAs_PjXmQ,6496
39
+ encommon/times/parse.py,sha256=KGHGdtimrqpbyTwjhZUPgXHQqGaeDdxX8t8PrVEbwSc,6626
40
40
  encommon/times/time.py,sha256=Px_9Ifae7GKSY557FAbG1g9cwy3a6VZL09puAbinztQ,11745
41
41
  encommon/times/timer.py,sha256=xxS6KVXFuRLq-RkXWMR7MMX5x0HGrEhLlOhRCecuCZY,3225
42
- encommon/times/timers.py,sha256=4kRUd_posGCLSi6hW8aBDypNgnUjnfkbuKpAr4mjOLg,9815
42
+ encommon/times/timers.py,sha256=DMcLJB5x_KLSicp-vuxYkAfwfgFMnLMXQOHebi_VWno,12252
43
43
  encommon/times/unitime.py,sha256=MwYUJBdX_Rj7pW8QoMtZMUyHa4lsdZKryTdBCpVjnpY,1316
44
44
  encommon/times/utils.py,sha256=PJ5QsKb3_pYEnD3Sz81d8QDhYQtTIj4HJfMoC9gNwmo,3100
45
45
  encommon/times/window.py,sha256=_b55R4U5X5oeTS2PbTZHfOaNANl2WM2TRCP4-J6QLnE,8423
46
- encommon/times/windows.py,sha256=RVrtIHyWLsl8pTXZ8gTlhbFY2ITvqQF65mRZxpzvDI4,11309
46
+ encommon/times/windows.py,sha256=Tfs9SF0PPhecCAA6Ck9IWpSSHu3VGqt0mmmRdoqJ02Y,14071
47
47
  encommon/times/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
48
48
  encommon/times/test/test_duration.py,sha256=3Tw6Y_ah36GCJl4vZ76z4Jt7rIxcm9P18-A69qsbLjI,4224
49
49
  encommon/times/test/test_params.py,sha256=kHvs-WvKfPQCdCDnPU9tAyMVXmzH3eUjwQN-QdWBeh4,1407
50
50
  encommon/times/test/test_parse.py,sha256=3Dihhu8xKmgbcq_dqKcO-itAeGtqAJxjGFQ6dPsJ4XM,4210
51
51
  encommon/times/test/test_time.py,sha256=XTgtsil2dgkeBUlJyORsNKUapcZWDFvOU-JwtypA6zw,2257
52
52
  encommon/times/test/test_timer.py,sha256=cBZvO-k-FG7k4LICLLGVFxNBJuTjH4-eL4FNaa14uyY,1563
53
- encommon/times/test/test_timers.py,sha256=HePWaNNH4MTDZoa2H-S_XkmN32lZLXW3g5xv-zTCyl0,3881
53
+ encommon/times/test/test_timers.py,sha256=gfRSJ97PTzID9veTqWuqlhzRhWav9aGzqltkPhqJG2I,3977
54
54
  encommon/times/test/test_unitime.py,sha256=5i4UjBCw8R9h-Lw963GfB_dHBMEQhjvv1k-t27Wyyls,510
55
55
  encommon/times/test/test_utils.py,sha256=WkzHJY6zOt02Ujg5FItOo1nPtktz5ss8ODmG1tRQaaw,2056
56
56
  encommon/times/test/test_window.py,sha256=6ySO5DaYzg1bsVNCqB6u71rKWc0vpolxQ09ruoswN2c,6138
57
- encommon/times/test/test_windows.py,sha256=jxaz8jMfKpr2OIdLPnaiXBefWFvThhHd01Kh6qJI98w,4706
57
+ encommon/times/test/test_windows.py,sha256=HCx3SmAgAcuFoAm4YbRVWooKO38fcajul1zf6rsTIUk,4810
58
58
  encommon/types/__init__.py,sha256=rly7loMD1R7YU83u90KqPYiifjZAX_UAXpVGcB_Xerk,1269
59
59
  encommon/types/classes.py,sha256=FYFTu8Uj-74JWudHOlhaOrsXXPxitorBfM9_QM3EGSU,1689
60
60
  encommon/types/dicts.py,sha256=IuLoVdtilhM83ujT74mcz0Zi1HI87P4k7wjnnyMxPag,2821
@@ -131,8 +131,8 @@ encommon/webkit/test/test_moderate.py,sha256=KitKGBtwHOQm0pXXZA5nl9MwAi2pbHOsKhM
131
131
  encommon/webkit/test/test_numeric.py,sha256=9Jqiyo-Bh572QJSyd3gqRwYTifnqqzE7_cNCmLn0CG0,3531
132
132
  encommon/webkit/test/test_statate.py,sha256=4VvmyJhsK3TSK-hq3TzkzwPkXY-GPTU_7uJf-zG_y_s,1760
133
133
  encommon/webkit/test/test_tagues.py,sha256=LQWk6rSBoBxAu-YmUOU8uWNki5RBzk5lp0dbFpySg68,1431
134
- encommon-0.22.9.dist-info/licenses/LICENSE,sha256=otnXKCtMjPlbHs0wgZ_BWULrp3g_2dWQJ6icRk9nkgg,1071
135
- encommon-0.22.9.dist-info/METADATA,sha256=rciCC92RTbn2TL1EIg2D-LN5eKCC0v9k2ALxVHLf3iI,4304
136
- encommon-0.22.9.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
137
- encommon-0.22.9.dist-info/top_level.txt,sha256=bP8q7-5tLDNm-3XPlqn_bDENfYNug5801H_xfz3BEAM,9
138
- encommon-0.22.9.dist-info/RECORD,,
134
+ encommon-0.22.10.dist-info/licenses/LICENSE,sha256=otnXKCtMjPlbHs0wgZ_BWULrp3g_2dWQJ6icRk9nkgg,1071
135
+ encommon-0.22.10.dist-info/METADATA,sha256=XuW6IBVPYWx6Weg-oBCP_FSG9SAASWlqt6Y-hWOA-nY,4305
136
+ encommon-0.22.10.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
137
+ encommon-0.22.10.dist-info/top_level.txt,sha256=bP8q7-5tLDNm-3XPlqn_bDENfYNug5801H_xfz3BEAM,9
138
+ encommon-0.22.10.dist-info/RECORD,,