encommon 0.22.8__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,152 +399,146 @@ 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
303
-
304
- session = self.store_session
305
-
306
- config = params.windows
417
+ childs = self.__childs
307
418
 
308
419
 
309
- _table = WindowsTable
310
- _group = _table.group
311
- _unique = _table.unique
420
+ inserts: list[DictStrAny] = []
312
421
 
313
- query = (
314
- session.query(_table)
315
- .filter(_group == group)
316
- .order_by(_unique))
422
+ update = Time('now')
317
423
 
318
- for record in query.all():
319
424
 
320
- unique = str(record.unique)
321
- next = str(record.next)
425
+ items = childs.items()
322
426
 
323
- if unique not in config:
324
- continue
427
+ for unique, cache in items:
325
428
 
326
- _config = config[unique]
429
+ _last = cache.last.subsec
430
+ _next = cache.next.subsec
431
+ _update = update.subsec
327
432
 
328
- _config.start = next
329
- _config.anchor = next
433
+ inputs: DictStrAny = {
434
+ 'group': group,
435
+ 'unique': unique,
436
+ 'last': _last,
437
+ 'next': _next,
438
+ 'update': _update}
330
439
 
440
+ inserts.append(inputs)
331
441
 
332
- items = config.items()
333
442
 
334
- for key, value in items:
443
+ with lock, sess as session:
335
444
 
336
- if key in windows:
445
+ for insert in inserts:
337
446
 
338
- window = windows[key]
447
+ session.merge(
448
+ table(**insert))
339
449
 
340
- window.update(value.start)
450
+ session.commit()
341
451
 
342
- continue
343
452
 
344
- _start = (
345
- value.start or start)
346
-
347
- _stop = (
348
- value.stop or stop)
453
+ def ready(
454
+ self,
455
+ unique: str,
456
+ update: bool = True,
457
+ ) -> bool:
458
+ """
459
+ Determine whether or not the appropriate time has passed.
349
460
 
350
- if _start < start:
351
- _start = start
461
+ :param unique: Unique identifier for the related child.
462
+ :param update: Determines whether or not time is updated.
463
+ :returns: Boolean indicating whether enough time passed.
464
+ """
352
465
 
353
- if _stop > stop:
354
- _stop = stop
466
+ childs = self.__childs
355
467
 
356
- _anchor = (
357
- value.anchor or _start)
468
+ if unique not in childs:
469
+ raise ValueError('unique')
358
470
 
359
- window = Window(
360
- value.window,
361
- start=_start,
362
- stop=_stop,
363
- anchor=_anchor,
364
- delay=value.delay)
471
+ child = childs[unique]
365
472
 
366
- windows[key] = window
473
+ ready = child.ready(update)
367
474
 
475
+ if ready is True:
476
+ self.save_children()
368
477
 
369
- self.__windows = windows
478
+ return ready
370
479
 
371
480
 
372
- def save_children(
481
+ def pause(
373
482
  self,
374
- ) -> None:
483
+ unique: str,
484
+ update: bool = True,
485
+ ) -> bool:
375
486
  """
376
- Save the child caches from the attribute into database.
487
+ Determine whether or not the appropriate time has passed.
488
+
489
+ :param unique: Unique identifier for the related child.
490
+ :param update: Determines whether or not time is updated.
491
+ :returns: Boolean indicating whether enough time passed.
377
492
  """
378
493
 
379
- windows = self.__windows
494
+ return not self.ready(
495
+ unique, update)
380
496
 
381
- group = self.__group
382
497
 
383
- session = self.store_session
498
+ def select(
499
+ self,
500
+ unique: str,
501
+ ) -> Optional[WindowsRecord]:
502
+ """
503
+ Return the record from within the table in the database.
384
504
 
505
+ :returns: Record from within the table in the database.
506
+ """
385
507
 
386
- items = windows.items()
508
+ sess = self.__session()
509
+ lock = self.__locker
387
510
 
388
- for unique, window in items:
511
+ table = self.__table
512
+ model = WindowsRecord
389
513
 
390
- update = Time('now')
514
+ table = self.__table
515
+ group = self.__group
391
516
 
392
- append = WindowsTable(
393
- group=group,
394
- unique=unique,
395
- last=window.last.subsec,
396
- next=window.next.subsec,
397
- update=update.subsec)
517
+ _unique = table.unique
518
+ _group = table.group
398
519
 
399
- session.merge(append)
400
520
 
521
+ with lock, sess as session:
401
522
 
402
- session.commit()
403
- session.close()
523
+ query = (
524
+ session.query(table)
525
+ .filter(_unique == unique)
526
+ .filter(_group == group))
404
527
 
528
+ _records = list(query.all())
405
529
 
406
- def ready(
407
- self,
408
- unique: str,
409
- update: bool = True,
410
- ) -> bool:
411
- """
412
- Determine whether or not the appropriate time has passed.
413
-
414
- :param unique: Unique identifier for the related child.
415
- :param update: Determines whether or not time is updated.
416
- :returns: Boolean indicating whether enough time passed.
417
- """
418
-
419
- windows = self.__windows
420
530
 
421
- if unique not in windows:
422
- raise ValueError('unique')
531
+ records = [
532
+ model(x)
533
+ for x in _records]
423
534
 
424
- window = windows[unique]
425
535
 
426
- ready = window.ready(update)
536
+ if len(records) == 0:
537
+ return None
427
538
 
428
- if ready is True:
429
- self.save_children()
539
+ assert len(records) == 1
430
540
 
431
- return ready
541
+ return records[0]
432
542
 
433
543
 
434
544
  def create(
@@ -444,20 +554,58 @@ class Windows:
444
554
  :returns: Newly constructed instance of related class.
445
555
  """
446
556
 
447
- config = (
448
- self.params
449
- .windows)
557
+ childs = self.__childs
558
+ _start = self.__start
559
+ _stop = self.__stop
450
560
 
451
- if unique in config:
561
+ if unique in childs:
452
562
  raise ValueError('unique')
453
563
 
454
- 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
455
604
 
456
- self.load_children()
457
605
 
458
606
  self.save_children()
459
607
 
460
- return self.children[unique]
608
+ return child
461
609
 
462
610
 
463
611
  def update(
@@ -472,14 +620,14 @@ class Windows:
472
620
  :param value: Override the time updated for window value.
473
621
  """
474
622
 
475
- windows = self.__windows
623
+ childs = self.__childs
476
624
 
477
- if unique not in windows:
625
+ if unique not in childs:
478
626
  raise ValueError('unique')
479
627
 
480
- window = windows[unique]
628
+ child = childs[unique]
481
629
 
482
- window.update(value)
630
+ child.update(value)
483
631
 
484
632
  self.save_children()
485
633
 
@@ -498,32 +646,26 @@ class Windows:
498
646
  :param unique: Unique identifier for the related child.
499
647
  """
500
648
 
501
- params = self.__params
502
- windows = self.__windows
649
+ sess = self.__session()
650
+ lock = self.__locker
651
+ childs = self.__childs
503
652
 
653
+ table = self.__table
504
654
  group = self.__group
505
655
 
506
- session = self.store_session
507
-
508
- config = params.windows
509
-
510
-
511
- if unique in config:
512
- del config[unique]
656
+ _unique = table.unique
657
+ _group = table.group
513
658
 
514
- if unique in windows:
515
- del windows[unique]
516
659
 
660
+ with lock, sess as session:
517
661
 
518
- _table = WindowsTable
519
- _group = _table.group
520
- _unique = _table.unique
662
+ (session.query(table)
663
+ .filter(_unique == unique)
664
+ .filter(_group == group)
665
+ .delete())
521
666
 
522
- (session.query(_table)
523
- .filter(_unique == unique)
524
- .filter(_group == group)
525
- .delete())
667
+ session.commit()
526
668
 
527
669
 
528
- session.commit()
529
- session.close()
670
+ if unique in childs:
671
+ del childs[unique]
encommon/version.txt CHANGED
@@ -1 +1 @@
1
- 0.22.8
1
+ 0.22.10
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: encommon
3
- Version: 0.22.8
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=PWO17KUk16MCfu9n1dOBerjjrIJCvNcG3hxrb1RUDCY,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=mdoOMF4Igyw-mZGMqr2e4s22iFCijeqamCfiyFrRjlY,10867
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=HTn34YvDS56rAFm6T0fQ0DE7zF2TvWWHJr7hxj6kwz4,4515
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.8.dist-info/licenses/LICENSE,sha256=otnXKCtMjPlbHs0wgZ_BWULrp3g_2dWQJ6icRk9nkgg,1071
135
- encommon-0.22.8.dist-info/METADATA,sha256=y0Sf05hR54o4Ofj2J8LN9jOqN5tiXTzjwA7Qy6np3vY,4304
136
- encommon-0.22.8.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
137
- encommon-0.22.8.dist-info/top_level.txt,sha256=bP8q7-5tLDNm-3XPlqn_bDENfYNug5801H_xfz3BEAM,9
138
- encommon-0.22.8.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,,