encommon 0.11.1__py3-none-any.whl → 0.12.1__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/config/logger.py +3 -0
- encommon/config/params.py +0 -2
- encommon/times/params.py +0 -4
- encommon/times/test/test_timers.py +38 -32
- encommon/times/test/test_windows.py +47 -45
- encommon/times/timers.py +107 -83
- encommon/times/windows.py +127 -100
- encommon/version.txt +1 -1
- {encommon-0.11.1.dist-info → encommon-0.12.1.dist-info}/METADATA +32 -14
- {encommon-0.11.1.dist-info → encommon-0.12.1.dist-info}/RECORD +13 -13
- {encommon-0.11.1.dist-info → encommon-0.12.1.dist-info}/LICENSE +0 -0
- {encommon-0.11.1.dist-info → encommon-0.12.1.dist-info}/WHEEL +0 -0
- {encommon-0.11.1.dist-info → encommon-0.12.1.dist-info}/top_level.txt +0 -0
encommon/config/logger.py
CHANGED
encommon/config/params.py
CHANGED
@@ -37,8 +37,6 @@ class LoggerParams(BaseModel, extra='forbid'):
|
|
37
37
|
:param stdo_level: Minimum level for the message to pass.
|
38
38
|
:param file_level: Minimum level for the message to pass.
|
39
39
|
:param file_path: Enables writing to the filesystem path.
|
40
|
-
:param data: Keyword arguments passed to Pydantic model.
|
41
|
-
Parameter is picked up by autodoc, please ignore.
|
42
40
|
"""
|
43
41
|
|
44
42
|
stdo_level: Optional[LOGLEVELS] = None
|
encommon/times/params.py
CHANGED
@@ -24,8 +24,6 @@ class TimerParams(BaseModel, extra='forbid'):
|
|
24
24
|
|
25
25
|
:param timer: Seconds that are used for related timer.
|
26
26
|
:param start: Optional time for when the timer started.
|
27
|
-
:param data: Keyword arguments passed to Pydantic model.
|
28
|
-
Parameter is picked up by autodoc, please ignore.
|
29
27
|
"""
|
30
28
|
|
31
29
|
timer: float
|
@@ -81,8 +79,6 @@ class WindowParams(BaseModel, extra='forbid'):
|
|
81
79
|
:param stop: Determine the ending for scheduling window.
|
82
80
|
:param anchor: Optionally define time anchor for window.
|
83
81
|
:param delay: Period of time schedulng will be delayed.
|
84
|
-
:param data: Keyword arguments passed to Pydantic model.
|
85
|
-
Parameter is picked up by autodoc, please ignore.
|
86
82
|
"""
|
87
83
|
|
88
84
|
window: SCHEDULE
|
@@ -17,6 +17,7 @@ from pytest import raises
|
|
17
17
|
from ..params import TimerParams
|
18
18
|
from ..params import TimersParams
|
19
19
|
from ..timers import Timers
|
20
|
+
from ..timers import TimersTable
|
20
21
|
from ..times import Times
|
21
22
|
from ...types import inrepr
|
22
23
|
from ...types import instr
|
@@ -34,40 +35,45 @@ def timers(
|
|
34
35
|
:returns: Newly constructed instance of related class.
|
35
36
|
"""
|
36
37
|
|
38
|
+
|
37
39
|
source: dict[str, Any] = {
|
38
40
|
'one': {'timer': 1},
|
39
41
|
'two': {'timer': 1}}
|
40
42
|
|
43
|
+
|
41
44
|
params = TimersParams(
|
42
45
|
timers=source)
|
43
46
|
|
47
|
+
store = (
|
48
|
+
f'sqlite:///{tmp_path}'
|
49
|
+
'/cache.db')
|
50
|
+
|
44
51
|
timers = Timers(
|
45
52
|
params,
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
sqlite.commit()
|
53
|
+
store=store)
|
54
|
+
|
55
|
+
session = timers.store_session
|
56
|
+
|
57
|
+
|
58
|
+
timer = TimersTable(
|
59
|
+
group='default',
|
60
|
+
unique='two',
|
61
|
+
update='1970-01-01T00:00:00Z')
|
62
|
+
|
63
|
+
session.add(timer)
|
64
|
+
|
65
|
+
session.commit()
|
66
|
+
|
67
|
+
|
68
|
+
timer = TimersTable(
|
69
|
+
group='default',
|
70
|
+
unique='tre',
|
71
|
+
update='1970-01-01T00:00:00Z')
|
72
|
+
|
73
|
+
session.add(timer)
|
74
|
+
|
75
|
+
session.commit()
|
76
|
+
|
71
77
|
|
72
78
|
timers.load_children()
|
73
79
|
|
@@ -89,10 +95,10 @@ def test_Timers(
|
|
89
95
|
|
90
96
|
assert attrs == [
|
91
97
|
'_Timers__params',
|
92
|
-
'
|
93
|
-
'_Timers__file',
|
94
|
-
'_Timers__table',
|
98
|
+
'_Timers__store',
|
95
99
|
'_Timers__group',
|
100
|
+
'_Timers__store_engine',
|
101
|
+
'_Timers__store_session',
|
96
102
|
'_Timers__timers']
|
97
103
|
|
98
104
|
|
@@ -109,13 +115,13 @@ def test_Timers(
|
|
109
115
|
|
110
116
|
assert timers.params is not None
|
111
117
|
|
112
|
-
assert timers.
|
118
|
+
assert timers.store[:6] == 'sqlite'
|
113
119
|
|
114
|
-
assert timers.
|
120
|
+
assert timers.group == 'default'
|
115
121
|
|
116
|
-
assert timers.
|
122
|
+
assert timers.store_engine is not None
|
117
123
|
|
118
|
-
assert timers.
|
124
|
+
assert timers.store_session is not None
|
119
125
|
|
120
126
|
assert len(timers.children) == 2
|
121
127
|
|
@@ -17,6 +17,7 @@ from pytest import raises
|
|
17
17
|
from ..params import WindowParams
|
18
18
|
from ..params import WindowsParams
|
19
19
|
from ..windows import Windows
|
20
|
+
from ..windows import WindowsTable
|
20
21
|
from ...types import inrepr
|
21
22
|
from ...types import instr
|
22
23
|
|
@@ -33,6 +34,7 @@ def windows(
|
|
33
34
|
:returns: Newly constructed instance of related class.
|
34
35
|
"""
|
35
36
|
|
37
|
+
|
36
38
|
source: dict[str, Any] = {
|
37
39
|
'one': WindowParams(
|
38
40
|
window='* * * * *',
|
@@ -45,46 +47,46 @@ def windows(
|
|
45
47
|
stop=620,
|
46
48
|
delay=10)}
|
47
49
|
|
50
|
+
|
48
51
|
params = WindowsParams(
|
49
52
|
windows=source)
|
50
53
|
|
54
|
+
store = (
|
55
|
+
f'sqlite:///{tmp_path}'
|
56
|
+
'/cache.db')
|
57
|
+
|
51
58
|
windows = Windows(
|
52
59
|
params,
|
53
60
|
start=310,
|
54
61
|
stop=610,
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
"1970-01-01T00:07:00Z",
|
84
|
-
"1970-01-01T01:00:00Z")
|
85
|
-
""") # noqa: LIT003
|
86
|
-
|
87
|
-
sqlite.commit()
|
62
|
+
store=store)
|
63
|
+
|
64
|
+
session = windows.store_session
|
65
|
+
|
66
|
+
|
67
|
+
window = WindowsTable(
|
68
|
+
group='default',
|
69
|
+
unique='two',
|
70
|
+
last='1970-01-01T00:06:00Z',
|
71
|
+
next='1970-01-01T00:07:00Z',
|
72
|
+
update='1970-01-01T01:00:00Z')
|
73
|
+
|
74
|
+
session.add(window)
|
75
|
+
|
76
|
+
session.commit()
|
77
|
+
|
78
|
+
|
79
|
+
window = WindowsTable(
|
80
|
+
group='default',
|
81
|
+
unique='tre',
|
82
|
+
last='1970-01-01T00:06:00Z',
|
83
|
+
next='1970-01-01T00:07:00Z',
|
84
|
+
update='1970-01-01T01:00:00Z')
|
85
|
+
|
86
|
+
session.add(window)
|
87
|
+
|
88
|
+
session.commit()
|
89
|
+
|
88
90
|
|
89
91
|
windows.load_children()
|
90
92
|
|
@@ -106,12 +108,12 @@ def test_Windows(
|
|
106
108
|
|
107
109
|
assert attrs == [
|
108
110
|
'_Windows__params',
|
111
|
+
'_Windows__store',
|
112
|
+
'_Windows__group',
|
113
|
+
'_Windows__store_engine',
|
114
|
+
'_Windows__store_session',
|
109
115
|
'_Windows__start',
|
110
116
|
'_Windows__stop',
|
111
|
-
'_Windows__sqlite',
|
112
|
-
'_Windows__file',
|
113
|
-
'_Windows__table',
|
114
|
-
'_Windows__group',
|
115
117
|
'_Windows__windows']
|
116
118
|
|
117
119
|
|
@@ -128,19 +130,19 @@ def test_Windows(
|
|
128
130
|
|
129
131
|
assert windows.params is not None
|
130
132
|
|
131
|
-
assert windows.
|
132
|
-
'1970-01-01T00:05:10Z')
|
133
|
+
assert windows.store[:6] == 'sqlite'
|
133
134
|
|
134
|
-
assert windows.
|
135
|
-
'1970-01-01T00:10:10Z')
|
135
|
+
assert windows.group == 'default'
|
136
136
|
|
137
|
-
assert windows.
|
137
|
+
assert windows.store_engine is not None
|
138
138
|
|
139
|
-
assert windows.
|
139
|
+
assert windows.store_session is not None
|
140
140
|
|
141
|
-
assert windows.
|
141
|
+
assert windows.start == (
|
142
|
+
'1970-01-01T00:05:10Z')
|
142
143
|
|
143
|
-
assert windows.
|
144
|
+
assert windows.stop == (
|
145
|
+
'1970-01-01T00:10:10Z')
|
144
146
|
|
145
147
|
assert len(windows.children) == 2
|
146
148
|
|
encommon/times/timers.py
CHANGED
@@ -8,35 +8,64 @@ is permitted, for more information consult the project license file.
|
|
8
8
|
|
9
9
|
|
10
10
|
from copy import deepcopy
|
11
|
-
from sqlite3 import Connection
|
12
|
-
from sqlite3 import connect as SQLite
|
13
11
|
from typing import Optional
|
14
12
|
from typing import TYPE_CHECKING
|
15
13
|
|
14
|
+
from sqlalchemy import Column
|
15
|
+
from sqlalchemy import String
|
16
|
+
from sqlalchemy import create_engine
|
17
|
+
from sqlalchemy.engine import Engine
|
18
|
+
from sqlalchemy.orm import DeclarativeBase
|
19
|
+
from sqlalchemy.orm import Session
|
20
|
+
from sqlalchemy.orm import sessionmaker
|
21
|
+
|
16
22
|
from .common import PARSABLE
|
23
|
+
from .params import TimersParams
|
17
24
|
from .timer import Timer
|
18
25
|
from .times import Times
|
19
26
|
|
20
27
|
if TYPE_CHECKING:
|
21
28
|
from .params import TimerParams
|
22
|
-
from .params import TimersParams
|
23
29
|
|
24
30
|
|
25
31
|
|
26
|
-
|
32
|
+
TIMERS = dict[str, Timer]
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
class SQLBase(DeclarativeBase):
|
27
37
|
"""
|
28
|
-
|
29
|
-
{0} (
|
30
|
-
"group" text not null,
|
31
|
-
"unique" text not null,
|
32
|
-
"update" text not null,
|
33
|
-
primary key (
|
34
|
-
"group", "unique"));
|
35
|
-
""") # noqa: LIT003
|
38
|
+
Some additional class that SQLAlchemy requires to work.
|
36
39
|
|
40
|
+
.. note::
|
41
|
+
Input parameters are not defined, check parent class.
|
42
|
+
"""
|
37
43
|
|
38
44
|
|
39
|
-
|
45
|
+
|
46
|
+
class TimersTable(SQLBase):
|
47
|
+
"""
|
48
|
+
Schematic for the database operations using SQLAlchemy.
|
49
|
+
|
50
|
+
.. note::
|
51
|
+
Fields are not completely documented for this model.
|
52
|
+
"""
|
53
|
+
|
54
|
+
group = Column(
|
55
|
+
String,
|
56
|
+
primary_key=True,
|
57
|
+
nullable=False)
|
58
|
+
|
59
|
+
unique = Column(
|
60
|
+
String,
|
61
|
+
primary_key=True,
|
62
|
+
nullable=False)
|
63
|
+
|
64
|
+
update = Column(
|
65
|
+
String,
|
66
|
+
nullable=False)
|
67
|
+
|
68
|
+
__tablename__ = 'timers'
|
40
69
|
|
41
70
|
|
42
71
|
|
@@ -65,19 +94,20 @@ class Timers:
|
|
65
94
|
True
|
66
95
|
|
67
96
|
:param params: Parameters for instantiating the instance.
|
68
|
-
:param
|
69
|
-
allowing for state retention between the executions.
|
70
|
-
:param table: Optional override for default table name.
|
97
|
+
:param store: Optional database path for keeping state.
|
71
98
|
:param group: Optional override for default group name.
|
72
99
|
"""
|
73
100
|
|
74
101
|
__params: 'TimersParams'
|
75
102
|
|
76
|
-
|
77
|
-
__file: str
|
78
|
-
__table: str
|
103
|
+
__store: str
|
79
104
|
__group: str
|
80
105
|
|
106
|
+
__store_engine: Engine
|
107
|
+
__store_session: (
|
108
|
+
# pylint: disable=unsubscriptable-object
|
109
|
+
sessionmaker[Session])
|
110
|
+
|
81
111
|
__timers: TIMERS
|
82
112
|
|
83
113
|
|
@@ -85,41 +115,52 @@ class Timers:
|
|
85
115
|
self,
|
86
116
|
params: Optional['TimersParams'] = None,
|
87
117
|
*,
|
88
|
-
|
89
|
-
table: str = 'timers',
|
118
|
+
store: str = 'sqlite:///:memory:',
|
90
119
|
group: str = 'default',
|
91
120
|
) -> None:
|
92
121
|
"""
|
93
122
|
Initialize instance for class using provided parameters.
|
94
123
|
"""
|
95
124
|
|
96
|
-
|
125
|
+
params = deepcopy(params)
|
97
126
|
|
98
127
|
if params is None:
|
99
128
|
params = TimersParams()
|
100
129
|
|
101
|
-
self.__params =
|
102
|
-
|
103
|
-
|
104
|
-
sqlite = SQLite(file)
|
130
|
+
self.__params = params
|
105
131
|
|
106
|
-
sqlite.execute(
|
107
|
-
CACHE_TABLE
|
108
|
-
.format(table))
|
109
132
|
|
110
|
-
|
111
|
-
|
112
|
-
self.__sqlite = sqlite
|
113
|
-
self.__file = file
|
114
|
-
self.__table = table
|
133
|
+
self.__store = store
|
115
134
|
self.__group = group
|
116
135
|
|
136
|
+
self.__make_engine()
|
137
|
+
|
117
138
|
|
118
139
|
self.__timers = {}
|
119
140
|
|
120
141
|
self.load_children()
|
121
142
|
|
122
143
|
|
144
|
+
def __make_engine(
|
145
|
+
self,
|
146
|
+
) -> None:
|
147
|
+
"""
|
148
|
+
Construct instances using the configuration parameters.
|
149
|
+
"""
|
150
|
+
|
151
|
+
store = self.__store
|
152
|
+
|
153
|
+
engine = create_engine(store)
|
154
|
+
|
155
|
+
(SQLBase.metadata
|
156
|
+
.create_all(engine))
|
157
|
+
|
158
|
+
session = sessionmaker(engine)
|
159
|
+
|
160
|
+
self.__store_engine = engine
|
161
|
+
self.__store_session = session
|
162
|
+
|
163
|
+
|
123
164
|
@property
|
124
165
|
def params(
|
125
166
|
self,
|
@@ -134,20 +175,20 @@ class Timers:
|
|
134
175
|
|
135
176
|
|
136
177
|
@property
|
137
|
-
def
|
178
|
+
def store(
|
138
179
|
self,
|
139
|
-
) ->
|
180
|
+
) -> str:
|
140
181
|
"""
|
141
182
|
Return the value for the attribute from class instance.
|
142
183
|
|
143
184
|
:returns: Value for the attribute from class instance.
|
144
185
|
"""
|
145
186
|
|
146
|
-
return self.
|
187
|
+
return self.__store
|
147
188
|
|
148
189
|
|
149
190
|
@property
|
150
|
-
def
|
191
|
+
def group(
|
151
192
|
self,
|
152
193
|
) -> str:
|
153
194
|
"""
|
@@ -156,33 +197,33 @@ class Timers:
|
|
156
197
|
:returns: Value for the attribute from class instance.
|
157
198
|
"""
|
158
199
|
|
159
|
-
return self.
|
200
|
+
return self.__group
|
160
201
|
|
161
202
|
|
162
203
|
@property
|
163
|
-
def
|
204
|
+
def store_engine(
|
164
205
|
self,
|
165
|
-
) ->
|
206
|
+
) -> Engine:
|
166
207
|
"""
|
167
208
|
Return the value for the attribute from class instance.
|
168
209
|
|
169
210
|
:returns: Value for the attribute from class instance.
|
170
211
|
"""
|
171
212
|
|
172
|
-
return self.
|
213
|
+
return self.__store_engine
|
173
214
|
|
174
215
|
|
175
216
|
@property
|
176
|
-
def
|
217
|
+
def store_session(
|
177
218
|
self,
|
178
|
-
) ->
|
219
|
+
) -> Session:
|
179
220
|
"""
|
180
221
|
Return the value for the attribute from class instance.
|
181
222
|
|
182
223
|
:returns: Value for the attribute from class instance.
|
183
224
|
"""
|
184
225
|
|
185
|
-
return self.
|
226
|
+
return self.__store_session()
|
186
227
|
|
187
228
|
|
188
229
|
@property
|
@@ -208,27 +249,26 @@ class Timers:
|
|
208
249
|
params = self.__params
|
209
250
|
timers = self.__timers
|
210
251
|
|
211
|
-
sqlite = self.__sqlite
|
212
|
-
table = self.__table
|
213
252
|
group = self.__group
|
214
253
|
|
254
|
+
session = self.store_session
|
215
255
|
|
216
256
|
config = params.timers
|
217
257
|
|
218
258
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
where "group"="{group}"
|
223
|
-
order by "unique" asc
|
224
|
-
""") # noqa: LIT003
|
259
|
+
_table = TimersTable
|
260
|
+
_group = _table.group
|
261
|
+
_unique = _table.unique
|
225
262
|
|
226
|
-
|
263
|
+
query = (
|
264
|
+
session.query(_table)
|
265
|
+
.filter(_group == group)
|
266
|
+
.order_by(_unique))
|
227
267
|
|
228
|
-
for record in
|
268
|
+
for record in query.all():
|
229
269
|
|
230
|
-
unique = record
|
231
|
-
update = record
|
270
|
+
unique = str(record.unique)
|
271
|
+
update = str(record.update)
|
232
272
|
|
233
273
|
if unique not in config:
|
234
274
|
continue
|
@@ -246,8 +286,7 @@ class Timers:
|
|
246
286
|
|
247
287
|
timer = timers[key]
|
248
288
|
|
249
|
-
timer.update(
|
250
|
-
value.start)
|
289
|
+
timer.update(value.start)
|
251
290
|
|
252
291
|
continue
|
253
292
|
|
@@ -270,42 +309,27 @@ class Timers:
|
|
270
309
|
|
271
310
|
timers = self.__timers
|
272
311
|
|
273
|
-
sqlite = self.__sqlite
|
274
|
-
table = self.__table
|
275
312
|
group = self.__group
|
276
313
|
|
314
|
+
session = self.store_session
|
277
315
|
|
278
|
-
insert = tuple[
|
279
|
-
str, # group
|
280
|
-
str, # unique
|
281
|
-
str] # update
|
282
|
-
|
283
|
-
inserts: list[insert] = []
|
284
316
|
|
285
317
|
items = timers.items()
|
286
318
|
|
287
319
|
for unique, timer in items:
|
288
320
|
|
289
|
-
|
290
|
-
group, unique,
|
291
|
-
Times('now').subsec)
|
292
|
-
|
293
|
-
inserts.append(append)
|
321
|
+
update = Times('now')
|
294
322
|
|
323
|
+
append = TimersTable(
|
324
|
+
group=group,
|
325
|
+
unique=unique,
|
326
|
+
update=update.subsec)
|
295
327
|
|
296
|
-
|
297
|
-
f"""
|
298
|
-
replace into {table}
|
299
|
-
("group", "unique",
|
300
|
-
"update")
|
301
|
-
values (?, ?, ?)
|
302
|
-
""") # noqa: LIT003
|
328
|
+
session.merge(append)
|
303
329
|
|
304
|
-
sqlite.executemany(
|
305
|
-
statement,
|
306
|
-
tuple(sorted(inserts)))
|
307
330
|
|
308
|
-
|
331
|
+
session.commit()
|
332
|
+
session.close()
|
309
333
|
|
310
334
|
|
311
335
|
def ready(
|
encommon/times/windows.py
CHANGED
@@ -8,37 +8,72 @@ is permitted, for more information consult the project license file.
|
|
8
8
|
|
9
9
|
|
10
10
|
from copy import deepcopy
|
11
|
-
from sqlite3 import Connection
|
12
|
-
from sqlite3 import connect as SQLite
|
13
11
|
from typing import Optional
|
14
12
|
from typing import TYPE_CHECKING
|
15
13
|
|
14
|
+
from sqlalchemy import Column
|
15
|
+
from sqlalchemy import String
|
16
|
+
from sqlalchemy import create_engine
|
17
|
+
from sqlalchemy.engine import Engine
|
18
|
+
from sqlalchemy.orm import DeclarativeBase
|
19
|
+
from sqlalchemy.orm import Session
|
20
|
+
from sqlalchemy.orm import sessionmaker
|
21
|
+
|
16
22
|
from .common import PARSABLE
|
23
|
+
from .params import WindowsParams
|
17
24
|
from .times import Times
|
18
25
|
from .window import Window
|
19
26
|
|
20
27
|
if TYPE_CHECKING:
|
21
28
|
from .params import WindowParams
|
22
|
-
from .params import WindowsParams
|
23
29
|
|
24
30
|
|
25
31
|
|
26
|
-
|
32
|
+
WINDOWS = dict[str, Window]
|
33
|
+
|
34
|
+
|
35
|
+
|
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.
|
27
42
|
"""
|
28
|
-
create table if not exists
|
29
|
-
{0} (
|
30
|
-
"group" text not null,
|
31
|
-
"unique" text not null,
|
32
|
-
"last" text not null,
|
33
|
-
"next" text not null,
|
34
|
-
"update" text not null,
|
35
|
-
primary key (
|
36
|
-
"group", "unique"));
|
37
|
-
""") # noqa: LIT003
|
38
43
|
|
39
44
|
|
40
45
|
|
41
|
-
|
46
|
+
class WindowsTable(SQLBase):
|
47
|
+
"""
|
48
|
+
Schematic for the database operations using SQLAlchemy.
|
49
|
+
|
50
|
+
.. note::
|
51
|
+
Fields are not completely documented for this model.
|
52
|
+
"""
|
53
|
+
|
54
|
+
group = Column(
|
55
|
+
String,
|
56
|
+
primary_key=True,
|
57
|
+
nullable=False)
|
58
|
+
|
59
|
+
unique = Column(
|
60
|
+
String,
|
61
|
+
primary_key=True,
|
62
|
+
nullable=False)
|
63
|
+
|
64
|
+
last = Column(
|
65
|
+
String,
|
66
|
+
nullable=False)
|
67
|
+
|
68
|
+
next = Column(
|
69
|
+
String,
|
70
|
+
nullable=False)
|
71
|
+
|
72
|
+
update = Column(
|
73
|
+
String,
|
74
|
+
nullable=False)
|
75
|
+
|
76
|
+
__tablename__ = 'windows'
|
42
77
|
|
43
78
|
|
44
79
|
|
@@ -65,45 +100,51 @@ class Windows:
|
|
65
100
|
:param params: Parameters for instantiating the instance.
|
66
101
|
:param start: Determine the start for scheduling window.
|
67
102
|
:param stop: Determine the ending for scheduling window.
|
68
|
-
:param
|
69
|
-
allowing for state retention between the executions.
|
70
|
-
:param table: Optional override for default table name.
|
103
|
+
:param store: Optional database path for keeping state.
|
71
104
|
:param group: Optional override for default group name.
|
72
105
|
"""
|
73
106
|
|
74
107
|
__params: 'WindowsParams'
|
75
108
|
|
109
|
+
__store: str
|
110
|
+
__group: str
|
111
|
+
|
112
|
+
__store_engine: Engine
|
113
|
+
__store_session: (
|
114
|
+
# pylint: disable=unsubscriptable-object
|
115
|
+
sessionmaker[Session])
|
116
|
+
|
76
117
|
__start: Times
|
77
118
|
__stop: Times
|
78
119
|
|
79
|
-
__sqlite: Connection
|
80
|
-
__file: str
|
81
|
-
__table: str
|
82
|
-
__group: str
|
83
|
-
|
84
120
|
__windows: WINDOWS
|
85
121
|
|
86
122
|
|
87
|
-
def __init__(
|
123
|
+
def __init__(
|
88
124
|
self,
|
89
125
|
params: Optional['WindowsParams'] = None,
|
90
126
|
start: PARSABLE = 'now',
|
91
127
|
stop: PARSABLE = '3000-01-01',
|
92
128
|
*,
|
93
|
-
|
94
|
-
table: str = 'windows',
|
129
|
+
store: str = 'sqlite:///:memory:',
|
95
130
|
group: str = 'default',
|
96
131
|
) -> None:
|
97
132
|
"""
|
98
133
|
Initialize instance for class using provided parameters.
|
99
134
|
"""
|
100
135
|
|
101
|
-
|
136
|
+
params = deepcopy(params)
|
102
137
|
|
103
138
|
if params is None:
|
104
139
|
params = WindowsParams()
|
105
140
|
|
106
|
-
self.__params =
|
141
|
+
self.__params = params
|
142
|
+
|
143
|
+
|
144
|
+
self.__store = store
|
145
|
+
self.__group = group
|
146
|
+
|
147
|
+
self.__make_engine()
|
107
148
|
|
108
149
|
|
109
150
|
start = Times(start)
|
@@ -115,23 +156,29 @@ class Windows:
|
|
115
156
|
self.__stop = stop
|
116
157
|
|
117
158
|
|
118
|
-
|
159
|
+
self.__windows = {}
|
119
160
|
|
120
|
-
|
121
|
-
CACHE_TABLE
|
122
|
-
.format(table))
|
161
|
+
self.load_children()
|
123
162
|
|
124
|
-
sqlite.commit()
|
125
163
|
|
126
|
-
|
127
|
-
self
|
128
|
-
|
129
|
-
|
164
|
+
def __make_engine(
|
165
|
+
self,
|
166
|
+
) -> None:
|
167
|
+
"""
|
168
|
+
Construct instances using the configuration parameters.
|
169
|
+
"""
|
130
170
|
|
171
|
+
store = self.__store
|
131
172
|
|
132
|
-
|
173
|
+
engine = create_engine(store)
|
133
174
|
|
134
|
-
|
175
|
+
(SQLBase.metadata
|
176
|
+
.create_all(engine))
|
177
|
+
|
178
|
+
session = sessionmaker(engine)
|
179
|
+
|
180
|
+
self.__store_engine = engine
|
181
|
+
self.__store_session = session
|
135
182
|
|
136
183
|
|
137
184
|
@property
|
@@ -148,81 +195,81 @@ class Windows:
|
|
148
195
|
|
149
196
|
|
150
197
|
@property
|
151
|
-
def
|
198
|
+
def store(
|
152
199
|
self,
|
153
|
-
) ->
|
200
|
+
) -> str:
|
154
201
|
"""
|
155
202
|
Return the value for the attribute from class instance.
|
156
203
|
|
157
204
|
:returns: Value for the attribute from class instance.
|
158
205
|
"""
|
159
206
|
|
160
|
-
return
|
207
|
+
return self.__store
|
161
208
|
|
162
209
|
|
163
210
|
@property
|
164
|
-
def
|
211
|
+
def group(
|
165
212
|
self,
|
166
|
-
) ->
|
213
|
+
) -> str:
|
167
214
|
"""
|
168
215
|
Return the value for the attribute from class instance.
|
169
216
|
|
170
217
|
:returns: Value for the attribute from class instance.
|
171
218
|
"""
|
172
219
|
|
173
|
-
return
|
220
|
+
return self.__group
|
174
221
|
|
175
222
|
|
176
223
|
@property
|
177
|
-
def
|
224
|
+
def store_engine(
|
178
225
|
self,
|
179
|
-
) ->
|
226
|
+
) -> Engine:
|
180
227
|
"""
|
181
228
|
Return the value for the attribute from class instance.
|
182
229
|
|
183
230
|
:returns: Value for the attribute from class instance.
|
184
231
|
"""
|
185
232
|
|
186
|
-
return self.
|
233
|
+
return self.__store_engine
|
187
234
|
|
188
235
|
|
189
236
|
@property
|
190
|
-
def
|
237
|
+
def store_session(
|
191
238
|
self,
|
192
|
-
) ->
|
239
|
+
) -> Session:
|
193
240
|
"""
|
194
241
|
Return the value for the attribute from class instance.
|
195
242
|
|
196
243
|
:returns: Value for the attribute from class instance.
|
197
244
|
"""
|
198
245
|
|
199
|
-
return self.
|
246
|
+
return self.__store_session()
|
200
247
|
|
201
248
|
|
202
249
|
@property
|
203
|
-
def
|
250
|
+
def start(
|
204
251
|
self,
|
205
|
-
) ->
|
252
|
+
) -> Times:
|
206
253
|
"""
|
207
254
|
Return the value for the attribute from class instance.
|
208
255
|
|
209
256
|
:returns: Value for the attribute from class instance.
|
210
257
|
"""
|
211
258
|
|
212
|
-
return self.
|
259
|
+
return Times(self.__start)
|
213
260
|
|
214
261
|
|
215
262
|
@property
|
216
|
-
def
|
263
|
+
def stop(
|
217
264
|
self,
|
218
|
-
) ->
|
265
|
+
) -> Times:
|
219
266
|
"""
|
220
267
|
Return the value for the attribute from class instance.
|
221
268
|
|
222
269
|
:returns: Value for the attribute from class instance.
|
223
270
|
"""
|
224
271
|
|
225
|
-
return self.
|
272
|
+
return Times(self.__stop)
|
226
273
|
|
227
274
|
|
228
275
|
@property
|
@@ -251,27 +298,26 @@ class Windows:
|
|
251
298
|
start = self.__start
|
252
299
|
stop = self.__stop
|
253
300
|
|
254
|
-
sqlite = self.__sqlite
|
255
|
-
table = self.__table
|
256
301
|
group = self.__group
|
257
302
|
|
303
|
+
session = self.store_session
|
258
304
|
|
259
305
|
config = params.windows
|
260
306
|
|
261
307
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
where "group"="{group}"
|
266
|
-
order by "unique" asc
|
267
|
-
""") # noqa: LIT003
|
308
|
+
_table = WindowsTable
|
309
|
+
_group = _table.group
|
310
|
+
_unique = _table.unique
|
268
311
|
|
269
|
-
|
312
|
+
query = (
|
313
|
+
session.query(_table)
|
314
|
+
.filter(_group == group)
|
315
|
+
.order_by(_unique))
|
270
316
|
|
271
|
-
for record in
|
317
|
+
for record in query.all():
|
272
318
|
|
273
|
-
unique = record
|
274
|
-
next = record
|
319
|
+
unique = str(record.unique)
|
320
|
+
next = str(record.next)
|
275
321
|
|
276
322
|
if unique not in config:
|
277
323
|
continue
|
@@ -290,8 +336,7 @@ class Windows:
|
|
290
336
|
|
291
337
|
window = windows[key]
|
292
338
|
|
293
|
-
window.update(
|
294
|
-
value.start)
|
339
|
+
window.update(value.start)
|
295
340
|
|
296
341
|
continue
|
297
342
|
|
@@ -332,47 +377,29 @@ class Windows:
|
|
332
377
|
|
333
378
|
windows = self.__windows
|
334
379
|
|
335
|
-
sqlite = self.__sqlite
|
336
|
-
table = self.__table
|
337
380
|
group = self.__group
|
338
381
|
|
382
|
+
session = self.store_session
|
339
383
|
|
340
|
-
insert = tuple[
|
341
|
-
str, # group
|
342
|
-
str, # unique
|
343
|
-
str, # last
|
344
|
-
str, # next
|
345
|
-
str] # update
|
346
|
-
|
347
|
-
inserts: list[insert] = []
|
348
384
|
|
349
385
|
items = windows.items()
|
350
386
|
|
351
387
|
for unique, window in items:
|
352
388
|
|
353
|
-
|
354
|
-
group, unique,
|
355
|
-
window.last.subsec,
|
356
|
-
window.next.subsec,
|
357
|
-
Times('now').subsec)
|
358
|
-
|
359
|
-
inserts.append(append)
|
389
|
+
update = Times('now')
|
360
390
|
|
391
|
+
append = WindowsTable(
|
392
|
+
group=group,
|
393
|
+
unique=unique,
|
394
|
+
last=window.last.subsec,
|
395
|
+
next=window.next.subsec,
|
396
|
+
update=update.subsec)
|
361
397
|
|
362
|
-
|
363
|
-
f"""
|
364
|
-
replace into {table}
|
365
|
-
("group", "unique",
|
366
|
-
"next", "last",
|
367
|
-
"update")
|
368
|
-
values (?, ?, ?, ?, ?)
|
369
|
-
""") # noqa: LIT003
|
398
|
+
session.merge(append)
|
370
399
|
|
371
|
-
sqlite.executemany(
|
372
|
-
statement,
|
373
|
-
tuple(sorted(inserts)))
|
374
400
|
|
375
|
-
|
401
|
+
session.commit()
|
402
|
+
session.close()
|
376
403
|
|
377
404
|
|
378
405
|
def ready(
|
encommon/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.12.1
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: encommon
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.12.1
|
4
4
|
Summary: Enasis Network Common Library
|
5
5
|
License: MIT
|
6
6
|
Classifier: Programming Language :: Python :: 3
|
@@ -15,6 +15,7 @@ Requires-Dist: pydantic
|
|
15
15
|
Requires-Dist: python-dateutil
|
16
16
|
Requires-Dist: pyyaml
|
17
17
|
Requires-Dist: snaptime
|
18
|
+
Requires-Dist: sqlalchemy
|
18
19
|
|
19
20
|
# Enasis Network Common Library
|
20
21
|
|
@@ -73,16 +74,33 @@ information found in the `htmlcov` folder in the root of the project.
|
|
73
74
|
make -s pytest
|
74
75
|
```
|
75
76
|
|
76
|
-
##
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
```
|
81
|
-
|
82
|
-
```
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
77
|
+
## Version management
|
78
|
+
:warning: Ensure that no changes are pending.
|
79
|
+
|
80
|
+
1. Rebuild the environment.
|
81
|
+
```
|
82
|
+
make -s check-revenv
|
83
|
+
```
|
84
|
+
|
85
|
+
1. Update the [version.txt](encommon/version.txt) file.
|
86
|
+
|
87
|
+
1. Push to the `main` branch.
|
88
|
+
|
89
|
+
1. Create [repository](https://github.com/enasisnetwork/encommon) release.
|
90
|
+
|
91
|
+
1. Build the Python package.<br>
|
92
|
+
```
|
93
|
+
make -s pypackage
|
94
|
+
```
|
95
|
+
|
96
|
+
1. Upload Python package to PyPi test.
|
97
|
+
```
|
98
|
+
make -s pypi-upload-test
|
99
|
+
```
|
100
|
+
|
101
|
+
1. Upload Python package to PyPi prod.
|
102
|
+
```
|
103
|
+
make -s pypi-upload-prod
|
104
|
+
```
|
105
|
+
|
106
|
+
1. Update [Read the Docs](https://encommon.readthedocs.io) documentation.
|
@@ -1,12 +1,12 @@
|
|
1
1
|
encommon/__init__.py,sha256=VoXUcphq-gcXCraaU47EtXBftF6UVuQPMGr0fuCTt9A,525
|
2
2
|
encommon/conftest.py,sha256=zoshfXjo2y_NsmWSHErOaTZx7A5tSYxNAhUf4TmUZKE,1827
|
3
3
|
encommon/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
encommon/version.txt,sha256=
|
4
|
+
encommon/version.txt,sha256=9u5pvxxLJ6JCJmzLWutKqMgwY0W56-T_czW4yUBFK4E,7
|
5
5
|
encommon/config/__init__.py,sha256=iZdbW7A4m7iN4xt5cEeQqo0Klqs-CaPLdD5ocLmUYi8,856
|
6
6
|
encommon/config/config.py,sha256=ldq1LfXGq0kfZwmlWE9mGG_hCdRuLT98QyLqnZY6ms8,5312
|
7
7
|
encommon/config/files.py,sha256=ueXiKTOqlQ4GKUT9lLyOlE-tfr6QAkSxdUs0VPbwEnE,2385
|
8
|
-
encommon/config/logger.py,sha256=
|
9
|
-
encommon/config/params.py,sha256=
|
8
|
+
encommon/config/logger.py,sha256=7qjujhs0pI02gazhGpPCNa18qnuYpajVCTDlBkCtiro,14217
|
9
|
+
encommon/config/params.py,sha256=xygONdnwagGn06791nTX_mCR9hmdFl60RMe7MZr6ICw,2192
|
10
10
|
encommon/config/paths.py,sha256=f0JDqkmd1xVd9KJ6s0b5KaFk-N6MlOjz4n1W39A5JHM,2533
|
11
11
|
encommon/config/utils.py,sha256=VzTpBSZ-l6codt6vk4p4SpcmKk-H1OBy-9IUBPKP3t4,2039
|
12
12
|
encommon/config/test/__init__.py,sha256=i0JAeRcM-0YH2StGfwpaDbZV9dVribNSgFDcYcPPay8,313
|
@@ -25,24 +25,24 @@ encommon/crypts/test/test_hashes.py,sha256=JYpPit7ISv6u-5-HbC3wSCxuieySDLKawgnE7
|
|
25
25
|
encommon/times/__init__.py,sha256=aa3Wb2WBpZcf_RBgZu4vM3lEyPZhyuZicG5Fcg0DgEI,931
|
26
26
|
encommon/times/common.py,sha256=g7kkZLyodZCIPpdiPCZh0-UMHwn-rwCv_Y6gdSvek6k,988
|
27
27
|
encommon/times/duration.py,sha256=LTROiKcRXvPcs2Gz9KaB5Cmxo9NXd3TcMo5-jnTxPo0,10794
|
28
|
-
encommon/times/params.py,sha256=
|
28
|
+
encommon/times/params.py,sha256=qwfy7cw9_UlWUm2xWm1aRjJJZzZp36w3Bo3Rc-HU2hM,3515
|
29
29
|
encommon/times/parse.py,sha256=DXoT_NyWL2Ea_j3vlGHMDY-5P6NBeYHyGhJoiavgBS0,6144
|
30
30
|
encommon/times/timer.py,sha256=19dt7A5nJEUdr_0p3WDFGO-Q49OHt3sgPW4R2zHoScU,2901
|
31
|
-
encommon/times/timers.py,sha256=
|
31
|
+
encommon/times/timers.py,sha256=uFzgfG1OFexXE-lW9muN_QYioDPXJMdOofpNxxuF_5Y,8696
|
32
32
|
encommon/times/times.py,sha256=FBOAVY1H21OV4BjGHj6iJrYbGQpSkWPj3Ss2Vepdvu4,9682
|
33
33
|
encommon/times/utils.py,sha256=PJ5QsKb3_pYEnD3Sz81d8QDhYQtTIj4HJfMoC9gNwmo,3100
|
34
34
|
encommon/times/window.py,sha256=3ctrDd0UWvnwrqxRZf7M-mVeEYVWvet6GZTj17YQ9sU,8526
|
35
|
-
encommon/times/windows.py,sha256=
|
35
|
+
encommon/times/windows.py,sha256=PKGE_8lUUZs6ZsCB3anFmFnGTKK3-G4R4_n98F74gaI,10287
|
36
36
|
encommon/times/test/__init__.py,sha256=PjrnBYT0efyvbaGeNx94dm3tP3EVHUHSVs-VGeLEv5g,218
|
37
37
|
encommon/times/test/test_duration.py,sha256=ofCBdQ4-tOKP5W5U2xyTaZrCVvD-dWEgnYoCvZ99MuA,4189
|
38
38
|
encommon/times/test/test_params.py,sha256=kHvs-WvKfPQCdCDnPU9tAyMVXmzH3eUjwQN-QdWBeh4,1407
|
39
39
|
encommon/times/test/test_parse.py,sha256=ozP8PBgIsqdknK8cEtlYA3KusKnJzbjfAUKhcFv_eFk,4054
|
40
40
|
encommon/times/test/test_timer.py,sha256=A5pBmkd1i71LTpG-uA9-9UGNJUK8tkw6by8Adm0AbGE,1400
|
41
|
-
encommon/times/test/test_timers.py,sha256=
|
41
|
+
encommon/times/test/test_timers.py,sha256=DxIiX4g7tbub4MAP3Z3-vAES5HbEzjDXMQPSAsIFavA,3845
|
42
42
|
encommon/times/test/test_times.py,sha256=vxEtXI9gYFlWnBLsyPyi17a96MJzgcI79SCy8U1Co8I,1748
|
43
43
|
encommon/times/test/test_utils.py,sha256=WkzHJY6zOt02Ujg5FItOo1nPtktz5ss8ODmG1tRQaaw,2056
|
44
44
|
encommon/times/test/test_window.py,sha256=Sx_fd0J1ofaFx52t-uWz9Isa9KqBxPFnynzfGfiG7uo,6098
|
45
|
-
encommon/times/test/test_windows.py,sha256=
|
45
|
+
encommon/times/test/test_windows.py,sha256=dY7QYQ5BCBfAGotHrmkWkPGjRsI2od-8PbWkPwZ-QIM,4643
|
46
46
|
encommon/types/__init__.py,sha256=L1pdigJyPNPEoAkkbCHM9IhmFtU2GjFRxHMRTAnPqKk,667
|
47
47
|
encommon/types/dicts.py,sha256=lC2FmPzMEj9L73jUjf3o6OVQ-LqK_3gp5nBwYibdGfo,2265
|
48
48
|
encommon/types/empty.py,sha256=n5y5maXkcM3xNYNYGK6iqvk98ivQSeguaedwc0HoMv4,2739
|
@@ -66,8 +66,8 @@ encommon/utils/test/test_match.py,sha256=QagKpTFdRo23-Y55fSaJrSMpt5jIebScKbz0h8t
|
|
66
66
|
encommon/utils/test/test_paths.py,sha256=1yiZp5PCxljGk0J6fwIfWOUl-KWz40INybrwrN3JIog,1945
|
67
67
|
encommon/utils/test/test_sample.py,sha256=sHAeWOL1mchTGYGQaFK_A3Z28tThuULumm9kQebnIdk,1710
|
68
68
|
encommon/utils/test/test_stdout.py,sha256=TA7xQuFoPZUYW2l00e04MGp4P9gHkkVxVflvPlhpQXg,4878
|
69
|
-
encommon-0.
|
70
|
-
encommon-0.
|
71
|
-
encommon-0.
|
72
|
-
encommon-0.
|
73
|
-
encommon-0.
|
69
|
+
encommon-0.12.1.dist-info/LICENSE,sha256=otnXKCtMjPlbHs0wgZ_BWULrp3g_2dWQJ6icRk9nkgg,1071
|
70
|
+
encommon-0.12.1.dist-info/METADATA,sha256=SjY2NeW39K-EjlErEdgmjS2069BIn39gle7zjAuqYcA,3362
|
71
|
+
encommon-0.12.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
72
|
+
encommon-0.12.1.dist-info/top_level.txt,sha256=bP8q7-5tLDNm-3XPlqn_bDENfYNug5801H_xfz3BEAM,9
|
73
|
+
encommon-0.12.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|