encommon 0.10.0__py3-none-any.whl → 0.11.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.
Files changed (45) hide show
  1. encommon/config/__init__.py +3 -3
  2. encommon/config/config.py +19 -7
  3. encommon/config/files.py +3 -3
  4. encommon/config/logger.py +39 -7
  5. encommon/config/params.py +21 -1
  6. encommon/config/paths.py +2 -2
  7. encommon/config/test/test_logger.py +4 -1
  8. encommon/config/test/{test_common.py → test_utils.py} +3 -3
  9. encommon/config/{common.py → utils.py} +1 -10
  10. encommon/conftest.py +2 -1
  11. encommon/crypts/crypts.py +68 -18
  12. encommon/crypts/params.py +14 -1
  13. encommon/crypts/test/test_crypts.py +56 -13
  14. encommon/times/__init__.py +14 -2
  15. encommon/times/common.py +0 -127
  16. encommon/times/params.py +155 -0
  17. encommon/times/parse.py +5 -5
  18. encommon/times/test/test_params.py +64 -0
  19. encommon/times/test/test_parse.py +1 -1
  20. encommon/times/test/test_timer.py +86 -0
  21. encommon/times/test/test_timers.py +81 -41
  22. encommon/times/test/{test_common.py → test_utils.py} +3 -3
  23. encommon/times/test/test_window.py +101 -51
  24. encommon/times/test/test_windows.py +250 -0
  25. encommon/times/timer.py +147 -0
  26. encommon/times/timers.py +217 -130
  27. encommon/times/times.py +6 -6
  28. encommon/times/utils.py +148 -0
  29. encommon/times/window.py +124 -85
  30. encommon/times/windows.py +472 -0
  31. encommon/types/notate.py +0 -2
  32. encommon/utils/__init__.py +2 -2
  33. encommon/utils/common.py +0 -39
  34. encommon/utils/files.py +71 -0
  35. encommon/utils/paths.py +1 -1
  36. encommon/utils/sample.py +2 -2
  37. encommon/utils/test/{test_common.py → test_files.py} +2 -2
  38. encommon/utils/test/test_paths.py +2 -1
  39. encommon/version.txt +1 -1
  40. {encommon-0.10.0.dist-info → encommon-0.11.1.dist-info}/METADATA +1 -1
  41. encommon-0.11.1.dist-info/RECORD +73 -0
  42. encommon-0.10.0.dist-info/RECORD +0 -65
  43. {encommon-0.10.0.dist-info → encommon-0.11.1.dist-info}/LICENSE +0 -0
  44. {encommon-0.10.0.dist-info → encommon-0.11.1.dist-info}/WHEEL +0 -0
  45. {encommon-0.10.0.dist-info → encommon-0.11.1.dist-info}/top_level.txt +0 -0
@@ -7,11 +7,13 @@ is permitted, for more information consult the project license file.
7
7
 
8
8
 
9
9
 
10
+ from time import sleep
10
11
  from typing import TYPE_CHECKING
11
12
 
12
13
  from pytest import fixture
13
14
  from pytest import mark
14
15
 
16
+ from ..times import Times
15
17
  from ..window import Window
16
18
  from ..window import window_croniter
17
19
  from ..window import window_interval
@@ -32,8 +34,10 @@ def window() -> Window:
32
34
  """
33
35
 
34
36
  return Window(
35
- schedule='* * * * *',
36
- start=330, stop=630)
37
+ window='* * * * *',
38
+ start=300,
39
+ stop=600,
40
+ delay=10)
37
41
 
38
42
 
39
43
 
@@ -50,14 +54,13 @@ def test_Window(
50
54
  attrs = list(window.__dict__)
51
55
 
52
56
  assert attrs == [
53
- '_Window__schedule',
57
+ '_Window__window',
54
58
  '_Window__start',
55
59
  '_Window__stop',
56
60
  '_Window__anchor',
57
61
  '_Window__delay',
58
- '_Window__wilast',
59
- '_Window__winext',
60
- '_Window__walked']
62
+ '_Window__wlast',
63
+ '_Window__wnext']
61
64
 
62
65
 
63
66
  assert inrepr(
@@ -71,21 +74,28 @@ def test_Window(
71
74
  window)
72
75
 
73
76
 
74
- assert window.schedule == '* * * * *'
77
+ assert window.window == '* * * * *'
75
78
 
76
- assert window.start == '1970-01-01T00:05:30Z'
79
+ assert window.start == (
80
+ '1970-01-01T00:05:00Z')
77
81
 
78
- assert window.stop == '1970-01-01T00:10:30Z'
82
+ assert window.stop == (
83
+ '1970-01-01T00:10:00Z')
79
84
 
80
85
  assert window.anchor == window.start
81
86
 
82
- assert window.delay == 0.0
87
+ assert str(window.delay) == '10.0'
83
88
 
84
- assert window.last == '1970-01-01T00:05:00Z'
89
+ assert window.last == (
90
+ '1970-01-01T00:04:00Z')
85
91
 
86
- assert window.next == '1970-01-01T00:06:00Z'
92
+ assert window.next == (
93
+ '1970-01-01T00:05:00Z')
87
94
 
88
- assert window.walked is False
95
+ assert window.latest == (
96
+ '1970-01-01T00:09:50Z')
97
+
98
+ assert not window.walked
89
99
 
90
100
 
91
101
 
@@ -100,59 +110,99 @@ def test_Window_cover(
100
110
 
101
111
 
102
112
  window = Window(
103
- schedule='* * * * *',
113
+ window={'minutes': 1},
104
114
  start=window.start,
105
115
  stop=window.stop)
106
116
 
107
- assert window.last == '1970-01-01T00:05:00Z'
108
- assert window.next == '1970-01-01T00:06:00Z'
109
- assert window.walked is False
117
+ assert window.last == (
118
+ '1970-01-01T00:04:00Z')
119
+
120
+ assert window.next == (
121
+ '1970-01-01T00:05:00Z')
122
+
123
+ assert not window.walked
110
124
 
111
125
  for count in range(100):
112
- if window.walk() is False:
126
+ if window.walked:
113
127
  break
114
- assert window.walk(False)
128
+ assert window.ready()
129
+
130
+ assert count == 5
131
+ assert not window.ready()
132
+
133
+ assert window.last == (
134
+ '1970-01-01T00:09:00Z')
115
135
 
116
- assert count == 4
117
- assert not window.walk()
136
+ assert window.next == (
137
+ '1970-01-01T00:10:00Z')
118
138
 
119
- assert window.last == '1970-01-01T00:10:00Z'
120
- assert window.next == '1970-01-01T00:10:00Z'
121
- assert window.walked is True
139
+ assert window.walked
122
140
 
123
141
 
124
142
  window = Window(
125
- schedule={'minutes': 1},
143
+ window='* * * * *',
126
144
  start=window.start,
127
145
  stop=window.stop)
128
146
 
129
- assert window.last == '1970-01-01T00:04:30Z'
130
- assert window.next == '1970-01-01T00:05:30Z'
131
- assert window.walked is False
147
+ assert window.last == (
148
+ '1970-01-01T00:04:00Z')
149
+
150
+ assert window.next == (
151
+ '1970-01-01T00:05:00Z')
152
+
153
+ assert not window.walked
132
154
 
133
155
  for count in range(100):
134
- if window.walk() is False:
156
+ if window.walked:
135
157
  break
136
- assert window.walk(False)
158
+ assert window.ready()
137
159
 
138
160
  assert count == 5
139
- assert not window.walk()
161
+ assert not window.ready()
162
+
163
+ assert window.last == (
164
+ '1970-01-01T00:09:00Z')
165
+
166
+ assert window.next == (
167
+ '1970-01-01T00:10:00Z')
168
+
169
+ assert window.walked
140
170
 
141
- assert window.last == '1970-01-01T00:10:30Z'
142
- assert window.next == '1970-01-01T00:10:30Z'
143
- assert window.walked is True
171
+
172
+ anchor = Times('-0s@s')
173
+
174
+
175
+ window = Window(
176
+ window='* * * * *',
177
+ start=anchor.shift('+5m'),
178
+ stop=anchor.shift('+10m'))
179
+
180
+ assert not window.ready(False)
144
181
 
145
182
 
146
183
  window = Window(
147
- schedule='* * * * *',
148
- start='+5m', stop='+10m')
184
+ window={'seconds': 1},
185
+ start=anchor.shift('-5s'),
186
+ stop=anchor.shift('+5s'))
187
+
188
+ assert not window.walked
189
+
190
+ for count in range(100):
191
+ if window.walked:
192
+ break
193
+ if window.ready():
194
+ continue
195
+ sleep(0.25)
196
+
197
+ assert 16 <= count <= 32
198
+ assert not window.ready()
149
199
 
150
- assert not window.walk(False)
200
+ assert window.walked
151
201
 
152
202
 
153
203
 
154
204
  @mark.parametrize(
155
- 'schedule,anchor,backward,expect',
205
+ 'window,anchor,backward,expect',
156
206
  [('* * * * *', 0, False, (0, 60)),
157
207
  ('* * * * *', 1, False, (0, 60)),
158
208
  ('* * * * *', 0, True, (-60, 0)),
@@ -165,7 +215,7 @@ def test_Window_cover(
165
215
  ('0 * * * *', 3660, False, (3600, 7200)),
166
216
  ('0 * * * *', 3661, False, (3600, 7200))])
167
217
  def test_window_croniter(
168
- schedule: str,
218
+ window: str,
169
219
  anchor: 'PARSABLE',
170
220
  backward: bool,
171
221
  expect: tuple[int, int],
@@ -173,22 +223,22 @@ def test_window_croniter(
173
223
  """
174
224
  Perform various tests associated with relevant routines.
175
225
 
176
- :param schedule: Parameters for defining scheduled time.
226
+ :param window: Parameters for defining scheduled time.
177
227
  :param anchor: Optionally define time anchor for window.
178
228
  :param backward: Optionally operate the window backward.
179
229
  :param expect: Expected output from the testing routine.
180
230
  """
181
231
 
182
- window = window_croniter(
183
- schedule, anchor, backward)
232
+ croniter = window_croniter(
233
+ window, anchor, backward)
184
234
 
185
- assert window[0] == expect[0]
186
- assert window[1] == expect[1]
235
+ assert croniter[0] == expect[0]
236
+ assert croniter[1] == expect[1]
187
237
 
188
238
 
189
239
 
190
240
  @mark.parametrize(
191
- 'schedule,anchor,backward,expect',
241
+ 'window,anchor,backward,expect',
192
242
  [({'seconds': 60}, 0, False, (0, 60)),
193
243
  ({'seconds': 60}, 1, False, (1, 61)),
194
244
  ({'seconds': 60}, 0, True, (-60, 0)),
@@ -201,7 +251,7 @@ def test_window_croniter(
201
251
  ({'hours': 1}, 3660, False, (3660, 7260)),
202
252
  ({'hours': 1}, 3661, False, (3661, 7261))])
203
253
  def test_window_interval(
204
- schedule: dict[str, int],
254
+ window: dict[str, int],
205
255
  anchor: 'PARSABLE',
206
256
  backward: bool,
207
257
  expect: tuple[int, int],
@@ -209,14 +259,14 @@ def test_window_interval(
209
259
  """
210
260
  Perform various tests associated with relevant routines.
211
261
 
212
- :param schedule: Parameters for defining scheduled time.
262
+ :param window: Parameters for defining scheduled time.
213
263
  :param anchor: Optionally define time anchor for window.
214
264
  :param backward: Optionally operate the window backward.
215
265
  :param expect: Expected output from the testing routine.
216
266
  """
217
267
 
218
- window = window_interval(
219
- schedule, anchor, backward)
268
+ interval = window_interval(
269
+ window, anchor, backward)
220
270
 
221
- assert window[0] == expect[0]
222
- assert window[1] == expect[1]
271
+ assert interval[0] == expect[0]
272
+ assert interval[1] == expect[1]
@@ -0,0 +1,250 @@
1
+ """
2
+ Functions and routines associated with Enasis Network Common Library.
3
+
4
+ This file is part of Enasis Network software eco-system. Distribution
5
+ is permitted, for more information consult the project license file.
6
+ """
7
+
8
+
9
+
10
+ from pathlib import Path
11
+ from time import sleep
12
+ from typing import Any
13
+
14
+ from pytest import fixture
15
+ from pytest import raises
16
+
17
+ from ..params import WindowParams
18
+ from ..params import WindowsParams
19
+ from ..windows import Windows
20
+ from ...types import inrepr
21
+ from ...types import instr
22
+
23
+
24
+
25
+ @fixture
26
+ def windows(
27
+ tmp_path: Path,
28
+ ) -> Windows:
29
+ """
30
+ Construct the instance for use in the downstream tests.
31
+
32
+ :param tmp_path: pytest object for temporal filesystem.
33
+ :returns: Newly constructed instance of related class.
34
+ """
35
+
36
+ source: dict[str, Any] = {
37
+ 'one': WindowParams(
38
+ window='* * * * *',
39
+ start=310,
40
+ stop=610,
41
+ delay=10),
42
+ 'two': WindowParams(
43
+ window='* * * * *',
44
+ start=300,
45
+ stop=620,
46
+ delay=10)}
47
+
48
+ params = WindowsParams(
49
+ windows=source)
50
+
51
+ windows = Windows(
52
+ params,
53
+ start=310,
54
+ stop=610,
55
+ file=f'{tmp_path}/cache.db')
56
+
57
+ sqlite = windows.sqlite
58
+
59
+ sqlite.execute(
60
+ """
61
+ insert into windows
62
+ ("group", "unique",
63
+ "last", "next",
64
+ "update")
65
+ values (
66
+ "default", "two",
67
+ "1970-01-01T00:06:00Z",
68
+ "1970-01-01T00:07:00Z",
69
+ "1970-01-01T01:00:00Z")
70
+ """) # noqa: LIT003
71
+
72
+ sqlite.commit()
73
+
74
+ sqlite.execute(
75
+ """
76
+ insert into windows
77
+ ("group", "unique",
78
+ "last", "next",
79
+ "update")
80
+ values (
81
+ "default", "tre",
82
+ "1970-01-01T00:06:00Z",
83
+ "1970-01-01T00:07:00Z",
84
+ "1970-01-01T01:00:00Z")
85
+ """) # noqa: LIT003
86
+
87
+ sqlite.commit()
88
+
89
+ windows.load_children()
90
+
91
+ return windows
92
+
93
+
94
+
95
+ def test_Windows(
96
+ windows: 'Windows',
97
+ ) -> None:
98
+ """
99
+ Perform various tests associated with relevant routines.
100
+
101
+ :param windows: Primary class instance for window object.
102
+ """
103
+
104
+
105
+ attrs = list(windows.__dict__)
106
+
107
+ assert attrs == [
108
+ '_Windows__params',
109
+ '_Windows__start',
110
+ '_Windows__stop',
111
+ '_Windows__sqlite',
112
+ '_Windows__file',
113
+ '_Windows__table',
114
+ '_Windows__group',
115
+ '_Windows__windows']
116
+
117
+
118
+ assert inrepr(
119
+ 'windows.Windows object',
120
+ windows)
121
+
122
+ assert hash(windows) > 0
123
+
124
+ assert instr(
125
+ 'windows.Windows object',
126
+ windows)
127
+
128
+
129
+ assert windows.params is not None
130
+
131
+ assert windows.start == (
132
+ '1970-01-01T00:05:10Z')
133
+
134
+ assert windows.stop == (
135
+ '1970-01-01T00:10:10Z')
136
+
137
+ assert windows.sqlite is not None
138
+
139
+ assert windows.file[-8:] == 'cache.db'
140
+
141
+ assert windows.table == 'windows'
142
+
143
+ assert windows.group == 'default'
144
+
145
+ assert len(windows.children) == 2
146
+
147
+
148
+ window = windows.children['one']
149
+
150
+ assert window.next == (
151
+ '1970-01-01T00:06:00Z')
152
+
153
+ assert window.last == (
154
+ '1970-01-01T00:05:00Z')
155
+
156
+
157
+ window = windows.children['two']
158
+
159
+ assert window.next == (
160
+ '1970-01-01T00:08:00Z')
161
+
162
+ assert window.last == (
163
+ '1970-01-01T00:07:00Z')
164
+
165
+
166
+
167
+ def test_Windows_cover(
168
+ windows: 'Windows',
169
+ ) -> None:
170
+ """
171
+ Perform various tests associated with relevant routines.
172
+
173
+ :param windows: Primary class instance for window object.
174
+ """
175
+
176
+
177
+ assert windows.ready('two')
178
+
179
+ windows.update('two', '+1h')
180
+
181
+ assert not windows.ready('two')
182
+
183
+
184
+ windows = Windows()
185
+
186
+ params = WindowParams(window=1)
187
+
188
+ windows.create('fur', params)
189
+
190
+ assert not windows.ready('fur')
191
+
192
+ sleep(2)
193
+
194
+ assert windows.ready('fur')
195
+
196
+ windows.delete('fur')
197
+
198
+
199
+
200
+ def test_Windows_raises(
201
+ windows: Windows,
202
+ ) -> None:
203
+ """
204
+ Perform various tests associated with relevant routines.
205
+
206
+ :param windows: Primary class instance for window object.
207
+ """
208
+
209
+
210
+ _raises = raises(ValueError)
211
+
212
+ with _raises as reason:
213
+ windows.ready('dne')
214
+
215
+ _reason = str(reason.value)
216
+
217
+ assert _reason == 'unique'
218
+
219
+
220
+ _raises = raises(ValueError)
221
+
222
+ params = WindowParams(
223
+ window='* * * * *')
224
+
225
+ with _raises as reason:
226
+ windows.create('one', params)
227
+
228
+ _reason = str(reason.value)
229
+
230
+ assert _reason == 'unique'
231
+
232
+
233
+ _raises = raises(ValueError)
234
+
235
+ with _raises as reason:
236
+ windows.update('dne', 'now')
237
+
238
+ _reason = str(reason.value)
239
+
240
+ assert _reason == 'unique'
241
+
242
+
243
+ _raises = raises(ValueError)
244
+
245
+ with _raises as reason:
246
+ windows.delete('dne')
247
+
248
+ _reason = str(reason.value)
249
+
250
+ assert _reason == 'unique'
@@ -0,0 +1,147 @@
1
+ """
2
+ Functions and routines associated with Enasis Network Common Library.
3
+
4
+ This file is part of Enasis Network software eco-system. Distribution
5
+ is permitted, for more information consult the project license file.
6
+ """
7
+
8
+
9
+
10
+ from typing import Optional
11
+
12
+ from .common import NUMERIC
13
+ from .common import PARSABLE
14
+ from .times import Times
15
+
16
+
17
+
18
+ class Timer:
19
+ """
20
+ Process and operate the timer using provided interval.
21
+
22
+ .. testsetup::
23
+ >>> from time import sleep
24
+
25
+ Example
26
+ -------
27
+ >>> timer = Timer(1)
28
+ >>> timer.ready()
29
+ False
30
+ >>> sleep(1)
31
+ >>> timer.ready()
32
+ True
33
+
34
+ :param seconds: Period of time which must pass in timer.
35
+ :param started: Override default of using current time.
36
+ """
37
+
38
+ __timer: float
39
+ __times: Times
40
+
41
+
42
+ def __init__(
43
+ self,
44
+ timer: NUMERIC,
45
+ *,
46
+ start: Optional[PARSABLE] = None,
47
+ ) -> None:
48
+ """
49
+ Initialize instance for class using provided parameters.
50
+ """
51
+
52
+ timer = float(timer)
53
+ start = Times(start)
54
+
55
+ self.__timer = timer
56
+ self.__times = start
57
+
58
+
59
+ @property
60
+ def timer(
61
+ self,
62
+ ) -> float:
63
+ """
64
+ Return the value for the attribute from class instance.
65
+
66
+ :returns: Value for the attribute from class instance.
67
+ """
68
+
69
+ return self.__timer
70
+
71
+
72
+ @property
73
+ def times(
74
+ self,
75
+ ) -> Times:
76
+ """
77
+ Return the value for the attribute from class instance.
78
+
79
+ :returns: Value for the attribute from class instance.
80
+ """
81
+
82
+ return self.__times
83
+
84
+
85
+ @property
86
+ def since(
87
+ self,
88
+ ) -> float:
89
+ """
90
+ Return the seconds that have elapsed since the interval.
91
+
92
+ :returns: Seconds that have elapsed since the interval.
93
+ """
94
+
95
+ return self.times.since
96
+
97
+
98
+ @property
99
+ def remains(
100
+ self,
101
+ ) -> float:
102
+ """
103
+ Return the value for the attribute from class instance.
104
+
105
+ :returns: Value for the attribute from class instance.
106
+ """
107
+
108
+ timer = self.timer
109
+ since = self.since
110
+
111
+ return max(0.0, timer - since)
112
+
113
+
114
+ def ready(
115
+ self,
116
+ update: bool = True,
117
+ ) -> bool:
118
+ """
119
+ Determine whether or not the appropriate time has passed.
120
+
121
+ :param update: Determines whether or not time is updated.
122
+ :returns: Boolean indicating whether enough time passed.
123
+ """
124
+
125
+ if self.remains > 0:
126
+ return False
127
+
128
+ if update is True:
129
+ self.update('now')
130
+
131
+ return True
132
+
133
+
134
+ def update(
135
+ self,
136
+ value: Optional[PARSABLE] = None,
137
+ ) -> None:
138
+ """
139
+ Update the timer from the provided parasable time value.
140
+
141
+ :param value: Override the time updated for timer value.
142
+ """
143
+
144
+ value = Times(
145
+ value or 'now')
146
+
147
+ self.__times = value