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
encommon/times/common.py CHANGED
@@ -7,18 +7,11 @@ is permitted, for more information consult the project license file.
7
7
 
8
8
 
9
9
 
10
- from contextlib import suppress
11
10
  from datetime import datetime
12
- from datetime import timezone
13
- from datetime import tzinfo
14
11
  from re import compile
15
- from typing import Any
16
- from typing import Optional
17
12
  from typing import TYPE_CHECKING
18
13
  from typing import Union
19
14
 
20
- from dateutil.tz import gettz
21
-
22
15
  if TYPE_CHECKING:
23
16
  from .times import Times
24
17
 
@@ -68,123 +61,3 @@ STAMP_SUBSEC = (
68
61
 
69
62
  STAMP_HUMAN = (
70
63
  '%m/%d/%Y %I:%M%p %Z')
71
-
72
-
73
-
74
- def utcdatetime(
75
- *args: Any,
76
- **kwargs: Any,
77
- ) -> datetime:
78
- """
79
- Return the instance of datetime within the UTC timezone.
80
-
81
- .. warning::
82
- If no arguments are provided, returns current time.
83
-
84
- Example
85
- -------
86
- >>> utcdatetime(1970, 1, 1)
87
- datetime.datetime(1970, 1, 1, 0...
88
-
89
- :param args: Positional arguments passed for downstream.
90
- :param kwargs: Keyword arguments passed for downstream.
91
- :returns: Instance of datetime within the UTC timezone.
92
- """
93
-
94
- tzinfo = timezone.utc
95
-
96
- if not args and not kwargs:
97
- return datetime.now(tz=tzinfo)
98
-
99
- if 'tzinfo' not in kwargs:
100
- kwargs['tzinfo'] = tzinfo
101
-
102
- return (
103
- datetime(*args, **kwargs)
104
- .astimezone(timezone.utc))
105
-
106
-
107
-
108
- def strptime(
109
- source: str,
110
- formats: str | list[str],
111
- ) -> datetime:
112
- """
113
- Parse provided time value with various supported formats.
114
-
115
- Example
116
- -------
117
- >>> strptime('2023', '%Y')
118
- datetime.datetime(2023, 1, 1, 0...
119
-
120
- :param source: Time in various forms that will be parsed.
121
- :param formats: Various formats compatable with strptime.
122
- :returns: Python datetime object containing related time.
123
- """
124
-
125
- tzinfo = timezone.utc
126
-
127
- if isinstance(formats, str):
128
- formats = [formats]
129
-
130
-
131
- def _strptime(
132
- format: str,
133
- ) -> datetime:
134
-
135
- return (
136
- datetime
137
- .strptime(source, format)
138
- .astimezone(tzinfo))
139
-
140
-
141
- for format in formats:
142
-
143
- with suppress(ValueError):
144
- return _strptime(format)
145
-
146
-
147
- raise ValueError('invalid')
148
-
149
-
150
-
151
- def strftime(
152
- source: datetime,
153
- format: str,
154
- ) -> str:
155
- """
156
- Return the timestamp string for datetime object provided.
157
-
158
- .. note::
159
- This function is extremely pedantic and cosmetic.
160
-
161
- :param source: Python datetime instance containing source.
162
- :param format: Format for the timestamp string returned.
163
- :returns: Timestamp string for datetime object provided.
164
- """
165
-
166
- return (
167
- datetime
168
- .strftime(source, format))
169
-
170
-
171
-
172
- def findtz(
173
- tzname: Optional[str] = None,
174
- ) -> tzinfo:
175
- """
176
- Return the located timezone object for the provided name.
177
-
178
- :param tzname: Name of the timezone associated to source.
179
- :returns: Located timezone object for the provided name.
180
- """
181
-
182
- if tzname is None:
183
- return timezone.utc
184
-
185
- tzinfo = gettz(tzname)
186
-
187
- if tzinfo is None:
188
- raise ValueError('tzname')
189
-
190
- return tzinfo
@@ -0,0 +1,155 @@
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 Any
11
+ from typing import Optional
12
+
13
+ from pydantic import BaseModel
14
+
15
+ from .common import PARSABLE
16
+ from .common import SCHEDULE
17
+ from .times import Times
18
+
19
+
20
+
21
+ class TimerParams(BaseModel, extra='forbid'):
22
+ """
23
+ Process and validate the core configuration parameters.
24
+
25
+ :param timer: Seconds that are used for related timer.
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
+ """
30
+
31
+ timer: float
32
+ start: Optional[str] = None
33
+
34
+
35
+ def __init__(
36
+ self,
37
+ timer: int | float,
38
+ start: Optional[PARSABLE] = None,
39
+ ) -> None:
40
+ """
41
+ Initialize instance for class using provided parameters.
42
+ """
43
+
44
+ if timer is not None:
45
+ timer = float(timer)
46
+
47
+ if start is not None:
48
+ start = Times(start)
49
+
50
+
51
+ data: dict[str, Any] = {
52
+ 'timer': timer}
53
+
54
+ if start is not None:
55
+ data['start'] = start.subsec
56
+
57
+
58
+ super().__init__(**data)
59
+
60
+
61
+
62
+ class TimersParams(BaseModel, extra='forbid'):
63
+ """
64
+ Process and validate the core configuration parameters.
65
+
66
+ :param timers: Seconds that are used for related timer.
67
+ :param data: Keyword arguments passed to Pydantic model.
68
+ Parameter is picked up by autodoc, please ignore.
69
+ """
70
+
71
+ timers: dict[str, TimerParams] = {}
72
+
73
+
74
+
75
+ class WindowParams(BaseModel, extra='forbid'):
76
+ """
77
+ Process and validate the core configuration parameters.
78
+
79
+ :param window: Parameters for defining scheduled time.
80
+ :param start: Determine the start for scheduling window.
81
+ :param stop: Determine the ending for scheduling window.
82
+ :param anchor: Optionally define time anchor for window.
83
+ :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
+ """
87
+
88
+ window: SCHEDULE
89
+
90
+ start: Optional[str] = None
91
+ stop: Optional[str] = None
92
+ anchor: Optional[str] = None
93
+ delay: float = 0.0
94
+
95
+
96
+ def __init__(
97
+ self,
98
+ window: SCHEDULE | int,
99
+ start: Optional[PARSABLE] = None,
100
+ stop: Optional[PARSABLE] = None,
101
+ anchor: Optional[PARSABLE] = None,
102
+ delay: Optional[int | float] = None,
103
+ ) -> None:
104
+ """
105
+ Initialize instance for class using provided parameters.
106
+ """
107
+
108
+
109
+ if isinstance(window, int):
110
+ window = {'seconds': window}
111
+
112
+
113
+ if start is not None:
114
+ start = Times(start)
115
+
116
+ if stop is not None:
117
+ stop = Times(stop)
118
+
119
+ if anchor is not None:
120
+ anchor = Times(anchor)
121
+
122
+ if delay is not None:
123
+ delay = float(delay)
124
+
125
+
126
+ data: dict[str, Any] = {
127
+ 'window': window}
128
+
129
+ if start is not None:
130
+ data['start'] = start.subsec
131
+
132
+ if stop is not None:
133
+ data['stop'] = stop.subsec
134
+
135
+ if anchor is not None:
136
+ data['anchor'] = anchor.subsec
137
+
138
+ if delay is not None:
139
+ data['delay'] = delay
140
+
141
+
142
+ super().__init__(**data)
143
+
144
+
145
+
146
+ class WindowsParams(BaseModel, extra='forbid'):
147
+ """
148
+ Process and validate the core configuration parameters.
149
+
150
+ :param windows: Parameters for defining scheduled time.
151
+ :param data: Keyword arguments passed to Pydantic model.
152
+ Parameter is picked up by autodoc, please ignore.
153
+ """
154
+
155
+ windows: dict[str, WindowParams] = {}
encommon/times/parse.py CHANGED
@@ -22,9 +22,9 @@ from .common import NUMERISH
22
22
  from .common import PARSABLE
23
23
  from .common import SNAPABLE
24
24
  from .common import STRINGNOW
25
- from .common import findtz
26
- from .common import strptime
27
- from .common import utcdatetime
25
+ from .utils import findtz
26
+ from .utils import strptime
27
+ from .utils import utcdatetime
28
28
 
29
29
  if TYPE_CHECKING:
30
30
  from .times import Times # noqa: F401
@@ -201,7 +201,7 @@ def since_time(
201
201
  stop: Optional[PARSABLE] = None,
202
202
  ) -> float:
203
203
  """
204
- Determine the time in seconds that occured between values.
204
+ Determine the time in seconds occurring between values.
205
205
 
206
206
  Example
207
207
  -------
@@ -212,7 +212,7 @@ def since_time(
212
212
 
213
213
  :param start: Time in various forms that will be parsed.
214
214
  :param stop: Time in various forms that will be parsed.
215
- :returns: Time in seconds that occured between the values.
215
+ :returns: Time in seconds occurring between the values.
216
216
  """
217
217
 
218
218
  start = parse_time(start)
@@ -0,0 +1,64 @@
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 ..params import TimerParams
11
+ from ..params import WindowParams
12
+
13
+
14
+
15
+ def test_TimerParams() -> None:
16
+ """
17
+ Perform various tests associated with relevant routines.
18
+ """
19
+
20
+ params = TimerParams(
21
+ timer=1,
22
+ start='1980-01-01T00:00:00Z')
23
+
24
+ assert params.start == (
25
+ '1980-01-01T00:00:00.000000+0000')
26
+
27
+
28
+
29
+ def test_WindowParams() -> None:
30
+ """
31
+ Perform various tests associated with relevant routines.
32
+ """
33
+
34
+
35
+ params = WindowParams(
36
+ window='* * * * *',
37
+ start='1980-01-01T00:00:00Z',
38
+ stop='1980-01-02T00:00:00Z',
39
+ anchor='1980-01-01T00:00:00Z',
40
+ delay=10)
41
+
42
+ assert params.start == (
43
+ '1980-01-01T00:00:00.000000+0000')
44
+
45
+ assert params.stop == (
46
+ '1980-01-02T00:00:00.000000+0000')
47
+
48
+ assert str(params.delay) == '10.0'
49
+
50
+
51
+ params = WindowParams(
52
+ window=60,
53
+ start='1980-01-01T00:00:00Z',
54
+ stop='1980-01-02T00:00:00Z',
55
+ anchor='1980-01-01T00:00:00Z',
56
+ delay=10)
57
+
58
+ assert params.start == (
59
+ '1980-01-01T00:00:00.000000+0000')
60
+
61
+ assert params.stop == (
62
+ '1980-01-02T00:00:00.000000+0000')
63
+
64
+ assert str(params.delay) == '10.0'
@@ -11,11 +11,11 @@ from datetime import timedelta
11
11
 
12
12
  from pytest import mark
13
13
 
14
- from ..common import utcdatetime
15
14
  from ..parse import parse_time
16
15
  from ..parse import shift_time
17
16
  from ..parse import since_time
18
17
  from ..parse import string_time
18
+ from ..utils import utcdatetime
19
19
 
20
20
 
21
21
 
@@ -0,0 +1,86 @@
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 time import sleep
11
+
12
+ from pytest import fixture
13
+
14
+ from ..timer import Timer
15
+ from ..times import Times
16
+ from ...types import inrepr
17
+ from ...types import instr
18
+
19
+
20
+
21
+ @fixture
22
+ def timer() -> Timer:
23
+ """
24
+ Construct the instance for use in the downstream tests.
25
+
26
+ :returns: Newly constructed instance of related class.
27
+ """
28
+
29
+ return Timer(1)
30
+
31
+
32
+
33
+ def test_Timer(
34
+ timer: Timer,
35
+ ) -> None:
36
+ """
37
+ Perform various tests associated with relevant routines.
38
+
39
+ :param timer: Primary class instance for timer object.
40
+ """
41
+
42
+
43
+ attrs = list(timer.__dict__)
44
+
45
+ assert attrs == [
46
+ '_Timer__timer',
47
+ '_Timer__times']
48
+
49
+
50
+ assert inrepr(
51
+ 'timer.Timer object',
52
+ timer)
53
+
54
+ assert hash(timer) > 0
55
+
56
+ assert instr(
57
+ 'timer.Timer object',
58
+ timer)
59
+
60
+
61
+ assert timer.timer == 1
62
+
63
+ assert timer.times >= Times('-1s')
64
+
65
+ assert timer.since <= 1
66
+
67
+ assert timer.remains <= 1
68
+
69
+ assert not timer.ready()
70
+
71
+
72
+ sleep(1)
73
+
74
+ assert timer.since > 1
75
+
76
+ assert timer.remains == 0
77
+
78
+ assert timer.ready()
79
+
80
+ assert not timer.ready()
81
+
82
+ timer.update('1980-01-01')
83
+
84
+ assert timer.ready()
85
+
86
+ assert not timer.ready()
@@ -9,11 +9,15 @@ is permitted, for more information consult the project license file.
9
9
 
10
10
  from pathlib import Path
11
11
  from time import sleep
12
+ from typing import Any
12
13
 
13
14
  from pytest import fixture
14
15
  from pytest import raises
15
16
 
17
+ from ..params import TimerParams
18
+ from ..params import TimersParams
16
19
  from ..timers import Timers
20
+ from ..times import Times
17
21
  from ...types import inrepr
18
22
  from ...types import instr
19
23
 
@@ -30,10 +34,45 @@ def timers(
30
34
  :returns: Newly constructed instance of related class.
31
35
  """
32
36
 
33
- return Timers(
34
- timers={'one': 1},
37
+ source: dict[str, Any] = {
38
+ 'one': {'timer': 1},
39
+ 'two': {'timer': 1}}
40
+
41
+ params = TimersParams(
42
+ timers=source)
43
+
44
+ timers = Timers(
45
+ params,
35
46
  file=f'{tmp_path}/cache.db')
36
47
 
48
+ sqlite = timers.sqlite
49
+
50
+ sqlite.execute(
51
+ """
52
+ insert into timers
53
+ ("group", "unique",
54
+ "update")
55
+ values (
56
+ "default", "two",
57
+ "1970-01-01T00:00:00Z")
58
+ """) # noqa: LIT003
59
+
60
+ sqlite.execute(
61
+ """
62
+ insert into timers
63
+ ("group", "unique",
64
+ "update")
65
+ values (
66
+ "default", "tre",
67
+ "1970-01-01T00:00:00Z")
68
+ """) # noqa: LIT003
69
+
70
+ sqlite.commit()
71
+
72
+ timers.load_children()
73
+
74
+ return timers
75
+
37
76
 
38
77
 
39
78
  def test_Timers(
@@ -49,11 +88,12 @@ def test_Timers(
49
88
  attrs = list(timers.__dict__)
50
89
 
51
90
  assert attrs == [
52
- '_Timers__config',
91
+ '_Timers__params',
53
92
  '_Timers__sqlite',
54
93
  '_Timers__file',
55
94
  '_Timers__table',
56
- '_Timers__cache']
95
+ '_Timers__group',
96
+ '_Timers__timers']
57
97
 
58
98
 
59
99
  assert inrepr(
@@ -67,7 +107,7 @@ def test_Timers(
67
107
  timers)
68
108
 
69
109
 
70
- assert timers.timers == {'one': 1}
110
+ assert timers.params is not None
71
111
 
72
112
  assert timers.sqlite is not None
73
113
 
@@ -75,36 +115,23 @@ def test_Timers(
75
115
 
76
116
  assert timers.table == 'timers'
77
117
 
78
- assert list(timers.cache) == ['one']
79
-
80
-
81
-
82
- def test_Timers_cover(
83
- timers: Timers,
84
- ) -> None:
85
- """
86
- Perform various tests associated with relevant routines.
87
-
88
- :param timers: Primary class instance for timers object.
89
- """
90
-
118
+ assert timers.group == 'default'
91
119
 
92
- assert not timers.ready('one')
120
+ assert len(timers.children) == 2
93
121
 
94
- sleep(1.1)
95
122
 
96
- assert timers.ready('one')
123
+ timer = timers.children['one']
97
124
 
125
+ assert timer.times >= Times('-1s')
98
126
 
99
- timers.create('two', 2, 0)
100
127
 
101
- assert timers.ready('two')
128
+ timer = timers.children['two']
102
129
 
103
- assert not timers.ready('two')
130
+ assert timer.times == '1970-01-01'
104
131
 
105
132
 
106
133
 
107
- def test_Timers_cache(
134
+ def test_Timers_cover(
108
135
  timers: Timers,
109
136
  ) -> None:
110
137
  """
@@ -113,27 +140,28 @@ def test_Timers_cache(
113
140
  :param timers: Primary class instance for timers object.
114
141
  """
115
142
 
116
- timers1 = Timers(
117
- timers={'uno': 1},
118
- file=timers.file)
119
143
 
120
- assert not timers1.ready('uno')
144
+ assert timers.ready('two')
145
+
146
+ timers.update('two', 'now')
147
+
148
+ assert not timers.ready('two')
149
+
150
+
151
+ timers = Timers()
152
+
121
153
 
122
- sleep(0.75)
154
+ params = TimerParams(timer=1)
123
155
 
124
- timers2 = Timers(
125
- timers={'uno': 1},
126
- file=timers.file)
156
+ timers.create('fur', params)
127
157
 
128
- assert not timers1.ready('uno')
129
- assert not timers2.ready('uno')
158
+ assert not timers.ready('fur')
130
159
 
131
- sleep(0.25)
160
+ sleep(1)
132
161
 
133
- timers2.load_cache()
162
+ assert timers.ready('fur')
134
163
 
135
- assert timers1.ready('uno')
136
- assert timers2.ready('uno')
164
+ timers.delete('fur')
137
165
 
138
166
 
139
167
 
@@ -157,10 +185,22 @@ def test_Timers_raises(
157
185
  assert _reason == 'unique'
158
186
 
159
187
 
188
+ _raises = raises(ValueError)
189
+
190
+ params = TimerParams(timer=1)
191
+
192
+ with _raises as reason:
193
+ timers.create('one', params)
194
+
195
+ _reason = str(reason.value)
196
+
197
+ assert _reason == 'unique'
198
+
199
+
160
200
  _raises = raises(ValueError)
161
201
 
162
202
  with _raises as reason:
163
- timers.update('dne')
203
+ timers.update('dne', 'now')
164
204
 
165
205
  _reason = str(reason.value)
166
206
 
@@ -170,7 +210,7 @@ def test_Timers_raises(
170
210
  _raises = raises(ValueError)
171
211
 
172
212
  with _raises as reason:
173
- timers.create('one', 1)
213
+ timers.delete('dne')
174
214
 
175
215
  _reason = str(reason.value)
176
216
 
@@ -13,9 +13,9 @@ from pytest import raises
13
13
 
14
14
  from ..common import STAMP_SIMPLE
15
15
  from ..common import UNIXEPOCH
16
- from ..common import findtz
17
- from ..common import strptime
18
- from ..common import utcdatetime
16
+ from ..utils import findtz
17
+ from ..utils import strptime
18
+ from ..utils import utcdatetime
19
19
 
20
20
 
21
21