encommon 0.22.9__py3-none-any.whl → 0.22.11__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/parse.py +9 -3
- encommon/times/test/test_timers.py +25 -18
- encommon/times/test/test_windows.py +29 -21
- encommon/times/timers.py +236 -125
- encommon/times/windows.py +275 -149
- encommon/types/__init__.py +2 -0
- encommon/types/notate.py +3 -2
- encommon/types/types.py +1 -0
- encommon/version.txt +1 -1
- {encommon-0.22.9.dist-info → encommon-0.22.11.dist-info}/METADATA +1 -1
- {encommon-0.22.9.dist-info → encommon-0.22.11.dist-info}/RECORD +14 -14
- {encommon-0.22.9.dist-info → encommon-0.22.11.dist-info}/WHEEL +1 -1
- {encommon-0.22.9.dist-info → encommon-0.22.11.dist-info}/licenses/LICENSE +0 -0
- {encommon-0.22.9.dist-info → encommon-0.22.11.dist-info}/top_level.txt +0 -0
encommon/times/timers.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,9 @@ from .common import PARSABLE
|
|
23
28
|
from .params import TimersParams
|
24
29
|
from .time import Time
|
25
30
|
from .timer import Timer
|
31
|
+
from ..types import BaseModel
|
32
|
+
from ..types import DictStrAny
|
33
|
+
from ..types import LDictStrAny
|
26
34
|
|
27
35
|
if TYPE_CHECKING:
|
28
36
|
from .params import TimerParams
|
@@ -33,17 +41,7 @@ TIMERS = dict[str, Timer]
|
|
33
41
|
|
34
42
|
|
35
43
|
|
36
|
-
class
|
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 TimersTable(SQLBase):
|
44
|
+
class TimersTable(DeclarativeBase):
|
47
45
|
"""
|
48
46
|
Schematic for the database operations using SQLAlchemy.
|
49
47
|
|
@@ -69,7 +67,74 @@ class TimersTable(SQLBase):
|
|
69
67
|
String,
|
70
68
|
nullable=False)
|
71
69
|
|
72
|
-
|
70
|
+
|
71
|
+
|
72
|
+
class TimersRecord(BaseModel):
|
73
|
+
"""
|
74
|
+
Contain the information of the record from the database.
|
75
|
+
|
76
|
+
:param record: Record from the SQLAlchemy query routine.
|
77
|
+
"""
|
78
|
+
|
79
|
+
group: Annotated[
|
80
|
+
str,
|
81
|
+
Field(...,
|
82
|
+
description='Group the children by category',
|
83
|
+
min_length=1)]
|
84
|
+
|
85
|
+
unique: Annotated[
|
86
|
+
str,
|
87
|
+
Field(...,
|
88
|
+
description='Unique identifier for the child',
|
89
|
+
min_length=1)]
|
90
|
+
|
91
|
+
last: Annotated[
|
92
|
+
str,
|
93
|
+
Field(...,
|
94
|
+
description='Last interval for the period',
|
95
|
+
min_length=20,
|
96
|
+
max_length=32)]
|
97
|
+
|
98
|
+
update: Annotated[
|
99
|
+
str,
|
100
|
+
Field(...,
|
101
|
+
description='When the record was updated',
|
102
|
+
min_length=20,
|
103
|
+
max_length=32)]
|
104
|
+
|
105
|
+
|
106
|
+
def __init__(
|
107
|
+
self,
|
108
|
+
record: Optional[DeclarativeBase] = None,
|
109
|
+
) -> None:
|
110
|
+
"""
|
111
|
+
Initialize instance for class using provided parameters.
|
112
|
+
"""
|
113
|
+
|
114
|
+
fields = [
|
115
|
+
'group',
|
116
|
+
'unique',
|
117
|
+
'last',
|
118
|
+
'update']
|
119
|
+
|
120
|
+
params = {
|
121
|
+
x: getattr(record, x)
|
122
|
+
for x in fields}
|
123
|
+
|
124
|
+
|
125
|
+
timefs = [
|
126
|
+
'last',
|
127
|
+
'update']
|
128
|
+
|
129
|
+
params |= {
|
130
|
+
k: (Time(v).simple
|
131
|
+
if v else None)
|
132
|
+
for k, v in
|
133
|
+
params.items()
|
134
|
+
if k in timefs}
|
135
|
+
|
136
|
+
|
137
|
+
super().__init__(**params)
|
73
138
|
|
74
139
|
|
75
140
|
|
@@ -106,13 +171,15 @@ class Timers:
|
|
106
171
|
|
107
172
|
__store: str
|
108
173
|
__group: str
|
174
|
+
__table: Type[TimersTable]
|
175
|
+
__locker: Lock
|
109
176
|
|
110
177
|
__sengine: Engine
|
111
178
|
__session: (
|
112
179
|
# pylint: disable=unsubscriptable-object
|
113
180
|
sessionmaker[Session])
|
114
181
|
|
115
|
-
|
182
|
+
__childs: TIMERS
|
116
183
|
|
117
184
|
|
118
185
|
def __init__(
|
@@ -120,6 +187,7 @@ class Timers:
|
|
120
187
|
params: Optional['TimersParams'] = None,
|
121
188
|
*,
|
122
189
|
store: str = 'sqlite:///:memory:',
|
190
|
+
table: str = 'timers',
|
123
191
|
group: str = 'default',
|
124
192
|
) -> None:
|
125
193
|
"""
|
@@ -137,15 +205,25 @@ class Timers:
|
|
137
205
|
self.__store = store
|
138
206
|
self.__group = group
|
139
207
|
|
140
|
-
|
208
|
+
class SQLBase(DeclarativeBase):
|
209
|
+
pass
|
141
210
|
|
211
|
+
self.__table = type(
|
212
|
+
f'encommon_timers_{table}',
|
213
|
+
(SQLBase, TimersTable),
|
214
|
+
{'__tablename__': table})
|
142
215
|
|
143
|
-
self.
|
216
|
+
self.__locker = Lock()
|
144
217
|
|
145
|
-
self.
|
218
|
+
self.__build_engine()
|
146
219
|
|
147
220
|
|
148
|
-
|
221
|
+
self.__childs = {}
|
222
|
+
|
223
|
+
self.__build_objects()
|
224
|
+
|
225
|
+
|
226
|
+
def __build_engine(
|
149
227
|
self,
|
150
228
|
) -> None:
|
151
229
|
"""
|
@@ -156,7 +234,7 @@ class Timers:
|
|
156
234
|
self.__store,
|
157
235
|
pool_pre_ping=True)
|
158
236
|
|
159
|
-
(
|
237
|
+
(self.__table.metadata
|
160
238
|
.create_all(sengine))
|
161
239
|
|
162
240
|
session = (
|
@@ -166,6 +244,23 @@ class Timers:
|
|
166
244
|
self.__session = session
|
167
245
|
|
168
246
|
|
247
|
+
def __build_objects(
|
248
|
+
self,
|
249
|
+
) -> None:
|
250
|
+
"""
|
251
|
+
Construct instances using the configuration parameters.
|
252
|
+
"""
|
253
|
+
|
254
|
+
params = self.__params
|
255
|
+
|
256
|
+
items = (
|
257
|
+
params.timers
|
258
|
+
.items())
|
259
|
+
|
260
|
+
for name, item in items:
|
261
|
+
self.create(name, item)
|
262
|
+
|
263
|
+
|
169
264
|
@property
|
170
265
|
def params(
|
171
266
|
self,
|
@@ -205,6 +300,19 @@ class Timers:
|
|
205
300
|
return self.__group
|
206
301
|
|
207
302
|
|
303
|
+
@property
|
304
|
+
def store_table(
|
305
|
+
self,
|
306
|
+
) -> Type[TimersTable]:
|
307
|
+
"""
|
308
|
+
Return the value for the attribute from class instance.
|
309
|
+
|
310
|
+
:returns: Value for the attribute from class instance.
|
311
|
+
"""
|
312
|
+
|
313
|
+
return self.__table
|
314
|
+
|
315
|
+
|
208
316
|
@property
|
209
317
|
def store_engine(
|
210
318
|
self,
|
@@ -241,101 +349,53 @@ class Timers:
|
|
241
349
|
:returns: Value for the attribute from class instance.
|
242
350
|
"""
|
243
351
|
|
244
|
-
return dict(self.
|
352
|
+
return dict(self.__childs)
|
245
353
|
|
246
354
|
|
247
|
-
def
|
355
|
+
def save_children(
|
248
356
|
self,
|
249
357
|
) -> None:
|
250
358
|
"""
|
251
|
-
|
359
|
+
Save the child caches from the attribute into database.
|
252
360
|
"""
|
253
361
|
|
254
|
-
|
255
|
-
|
362
|
+
sess = self.__session()
|
363
|
+
lock = self.__locker
|
256
364
|
|
365
|
+
table = self.__table
|
257
366
|
group = self.__group
|
258
|
-
|
259
|
-
session = self.store_session
|
260
|
-
|
261
|
-
config = params.timers
|
367
|
+
childs = self.__childs
|
262
368
|
|
263
369
|
|
264
|
-
|
265
|
-
_group = _table.group
|
266
|
-
_unique = _table.unique
|
370
|
+
inserts: LDictStrAny = []
|
267
371
|
|
268
|
-
|
269
|
-
session.query(_table)
|
270
|
-
.filter(_group == group)
|
271
|
-
.order_by(_unique))
|
372
|
+
update = Time('now')
|
272
373
|
|
273
|
-
for record in query.all():
|
274
374
|
|
275
|
-
|
276
|
-
last = str(record.last)
|
375
|
+
items = childs.items()
|
277
376
|
|
278
|
-
|
279
|
-
continue
|
377
|
+
for unique, cache in items:
|
280
378
|
|
281
|
-
|
379
|
+
_last = cache.time.subsec
|
380
|
+
_update = update.subsec
|
282
381
|
|
283
|
-
|
382
|
+
inputs: DictStrAny = {
|
383
|
+
'group': group,
|
384
|
+
'unique': unique,
|
385
|
+
'last': _last,
|
386
|
+
'update': _update}
|
284
387
|
|
388
|
+
inserts.append(inputs)
|
285
389
|
|
286
|
-
items = config.items()
|
287
390
|
|
288
|
-
|
391
|
+
with lock, sess as session:
|
289
392
|
|
290
|
-
|
393
|
+
for insert in inserts:
|
291
394
|
|
292
|
-
|
395
|
+
session.merge(
|
396
|
+
table(**insert))
|
293
397
|
|
294
|
-
|
295
|
-
|
296
|
-
continue
|
297
|
-
|
298
|
-
timer = Timer(
|
299
|
-
value.timer,
|
300
|
-
start=value.start)
|
301
|
-
|
302
|
-
timers[key] = timer
|
303
|
-
|
304
|
-
|
305
|
-
self.__timers = timers
|
306
|
-
|
307
|
-
|
308
|
-
def save_children(
|
309
|
-
self,
|
310
|
-
) -> None:
|
311
|
-
"""
|
312
|
-
Save the child caches from the attribute into database.
|
313
|
-
"""
|
314
|
-
|
315
|
-
timers = self.__timers
|
316
|
-
|
317
|
-
group = self.__group
|
318
|
-
|
319
|
-
session = self.store_session
|
320
|
-
|
321
|
-
|
322
|
-
items = timers.items()
|
323
|
-
|
324
|
-
for unique, timer in items:
|
325
|
-
|
326
|
-
update = Time('now')
|
327
|
-
|
328
|
-
append = TimersTable(
|
329
|
-
group=group,
|
330
|
-
unique=unique,
|
331
|
-
last=timer.time.subsec,
|
332
|
-
update=update.subsec)
|
333
|
-
|
334
|
-
session.merge(append)
|
335
|
-
|
336
|
-
|
337
|
-
session.commit()
|
338
|
-
session.close()
|
398
|
+
session.commit()
|
339
399
|
|
340
400
|
|
341
401
|
def ready(
|
@@ -351,14 +411,14 @@ class Timers:
|
|
351
411
|
:returns: Boolean indicating whether enough time passed.
|
352
412
|
"""
|
353
413
|
|
354
|
-
|
414
|
+
childs = self.__childs
|
355
415
|
|
356
|
-
if unique not in
|
416
|
+
if unique not in childs:
|
357
417
|
raise ValueError('unique')
|
358
418
|
|
359
|
-
|
419
|
+
child = childs[unique]
|
360
420
|
|
361
|
-
ready =
|
421
|
+
ready = child.ready(update)
|
362
422
|
|
363
423
|
if ready is True:
|
364
424
|
self.save_children()
|
@@ -383,6 +443,52 @@ class Timers:
|
|
383
443
|
unique, update)
|
384
444
|
|
385
445
|
|
446
|
+
def select(
|
447
|
+
self,
|
448
|
+
unique: str,
|
449
|
+
) -> Optional[TimersRecord]:
|
450
|
+
"""
|
451
|
+
Return the record from within the table in the database.
|
452
|
+
|
453
|
+
:returns: Record from within the table in the database.
|
454
|
+
"""
|
455
|
+
|
456
|
+
sess = self.__session()
|
457
|
+
lock = self.__locker
|
458
|
+
|
459
|
+
table = self.__table
|
460
|
+
model = TimersRecord
|
461
|
+
|
462
|
+
table = self.__table
|
463
|
+
group = self.__group
|
464
|
+
|
465
|
+
_unique = table.unique
|
466
|
+
_group = table.group
|
467
|
+
|
468
|
+
|
469
|
+
with lock, sess as session:
|
470
|
+
|
471
|
+
query = (
|
472
|
+
session.query(table)
|
473
|
+
.filter(_unique == unique)
|
474
|
+
.filter(_group == group))
|
475
|
+
|
476
|
+
_records = list(query.all())
|
477
|
+
|
478
|
+
|
479
|
+
records = [
|
480
|
+
model(x)
|
481
|
+
for x in _records]
|
482
|
+
|
483
|
+
|
484
|
+
if len(records) == 0:
|
485
|
+
return None
|
486
|
+
|
487
|
+
assert len(records) == 1
|
488
|
+
|
489
|
+
return records[0]
|
490
|
+
|
491
|
+
|
386
492
|
def create(
|
387
493
|
self,
|
388
494
|
unique: str,
|
@@ -396,20 +502,31 @@ class Timers:
|
|
396
502
|
:returns: Newly constructed instance of related class.
|
397
503
|
"""
|
398
504
|
|
399
|
-
|
400
|
-
self.params
|
401
|
-
.timers)
|
505
|
+
childs = self.__childs
|
402
506
|
|
403
|
-
if unique in
|
507
|
+
if unique in childs:
|
404
508
|
raise ValueError('unique')
|
405
509
|
|
406
|
-
|
510
|
+
timer = params.timer
|
511
|
+
start = params.start
|
512
|
+
|
513
|
+
|
514
|
+
select = self.select(unique)
|
515
|
+
|
516
|
+
if select is not None:
|
517
|
+
start = select.last
|
518
|
+
|
519
|
+
|
520
|
+
child = Timer(
|
521
|
+
timer=timer,
|
522
|
+
start=start)
|
523
|
+
|
524
|
+
childs[unique] = child
|
407
525
|
|
408
|
-
self.load_children()
|
409
526
|
|
410
527
|
self.save_children()
|
411
528
|
|
412
|
-
return
|
529
|
+
return child
|
413
530
|
|
414
531
|
|
415
532
|
def update(
|
@@ -424,14 +541,14 @@ class Timers:
|
|
424
541
|
:param value: Override the time updated for timer value.
|
425
542
|
"""
|
426
543
|
|
427
|
-
|
544
|
+
childs = self.__childs
|
428
545
|
|
429
|
-
if unique not in
|
546
|
+
if unique not in childs:
|
430
547
|
raise ValueError('unique')
|
431
548
|
|
432
|
-
|
549
|
+
child = childs[unique]
|
433
550
|
|
434
|
-
|
551
|
+
child.update(value)
|
435
552
|
|
436
553
|
self.save_children()
|
437
554
|
|
@@ -450,32 +567,26 @@ class Timers:
|
|
450
567
|
:param unique: Unique identifier for the related child.
|
451
568
|
"""
|
452
569
|
|
453
|
-
|
454
|
-
|
570
|
+
sess = self.__session()
|
571
|
+
lock = self.__locker
|
572
|
+
childs = self.__childs
|
455
573
|
|
574
|
+
table = self.__table
|
456
575
|
group = self.__group
|
457
576
|
|
458
|
-
|
459
|
-
|
460
|
-
config = params.timers
|
461
|
-
|
462
|
-
|
463
|
-
if unique in config:
|
464
|
-
del config[unique]
|
577
|
+
_unique = table.unique
|
578
|
+
_group = table.group
|
465
579
|
|
466
|
-
if unique in timers:
|
467
|
-
del timers[unique]
|
468
580
|
|
581
|
+
with lock, sess as session:
|
469
582
|
|
470
|
-
|
471
|
-
|
472
|
-
|
583
|
+
(session.query(table)
|
584
|
+
.filter(_unique == unique)
|
585
|
+
.filter(_group == group)
|
586
|
+
.delete())
|
473
587
|
|
474
|
-
|
475
|
-
.filter(_unique == unique)
|
476
|
-
.filter(_group == group)
|
477
|
-
.delete())
|
588
|
+
session.commit()
|
478
589
|
|
479
590
|
|
480
|
-
|
481
|
-
|
591
|
+
if unique in childs:
|
592
|
+
del childs[unique]
|