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