encommon 0.7.6__py3-none-any.whl → 0.8.0__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 (53) hide show
  1. encommon/config/__init__.py +4 -0
  2. encommon/config/common.py +18 -14
  3. encommon/config/config.py +8 -5
  4. encommon/config/files.py +13 -7
  5. encommon/config/logger.py +94 -88
  6. encommon/config/params.py +1 -1
  7. encommon/config/paths.py +16 -8
  8. encommon/config/test/test_common.py +27 -4
  9. encommon/config/test/test_config.py +48 -82
  10. encommon/config/test/test_files.py +58 -43
  11. encommon/config/test/test_logger.py +129 -82
  12. encommon/config/test/test_paths.py +70 -30
  13. encommon/conftest.py +52 -12
  14. encommon/crypts/__init__.py +2 -0
  15. encommon/crypts/crypts.py +3 -1
  16. encommon/crypts/hashes.py +2 -2
  17. encommon/crypts/test/test_crypts.py +50 -28
  18. encommon/crypts/test/test_hashes.py +20 -18
  19. encommon/times/__init__.py +2 -0
  20. encommon/times/common.py +99 -15
  21. encommon/times/duration.py +50 -36
  22. encommon/times/parse.py +13 -25
  23. encommon/times/test/test_common.py +47 -16
  24. encommon/times/test/test_duration.py +104 -79
  25. encommon/times/test/test_parse.py +53 -63
  26. encommon/times/test/test_timers.py +90 -36
  27. encommon/times/test/test_times.py +21 -30
  28. encommon/times/test/test_window.py +73 -21
  29. encommon/times/timers.py +91 -58
  30. encommon/times/times.py +36 -34
  31. encommon/times/window.py +4 -4
  32. encommon/types/dicts.py +10 -4
  33. encommon/types/empty.py +7 -2
  34. encommon/types/strings.py +10 -0
  35. encommon/types/test/test_dicts.py +5 -5
  36. encommon/types/test/test_empty.py +4 -1
  37. encommon/types/test/test_strings.py +1 -1
  38. encommon/utils/__init__.py +4 -0
  39. encommon/utils/common.py +51 -6
  40. encommon/utils/match.py +1 -0
  41. encommon/utils/paths.py +42 -23
  42. encommon/utils/sample.py +31 -27
  43. encommon/utils/stdout.py +28 -17
  44. encommon/utils/test/test_common.py +35 -0
  45. encommon/utils/test/test_paths.py +3 -2
  46. encommon/utils/test/test_sample.py +28 -12
  47. encommon/version.txt +1 -1
  48. {encommon-0.7.6.dist-info → encommon-0.8.0.dist-info}/METADATA +1 -1
  49. encommon-0.8.0.dist-info/RECORD +63 -0
  50. encommon-0.7.6.dist-info/RECORD +0 -62
  51. {encommon-0.7.6.dist-info → encommon-0.8.0.dist-info}/LICENSE +0 -0
  52. {encommon-0.7.6.dist-info → encommon-0.8.0.dist-info}/WHEEL +0 -0
  53. {encommon-0.7.6.dist-info → encommon-0.8.0.dist-info}/top_level.txt +0 -0
@@ -8,53 +8,33 @@ is permitted, for more information consult the project license file.
8
8
 
9
9
 
10
10
  from pathlib import Path
11
+ from typing import TYPE_CHECKING
11
12
 
12
13
  from . import SAMPLES
13
- from ..config import Config
14
14
  from ..logger import Logger
15
15
  from ..params import Params
16
16
  from ... import ENPYRWS
17
- from ...crypts.crypts import Crypts
18
- from ...utils.sample import load_sample
19
- from ...utils.sample import prep_sample
17
+ from ... import PROJECT
18
+ from ...crypts import Crypts
19
+ from ...utils import load_sample
20
+ from ...utils import prep_sample
20
21
 
22
+ if TYPE_CHECKING:
23
+ from ..config import Config
21
24
 
22
25
 
23
- def test_Config( # noqa: CFQ001
24
- config_path: Path,
26
+
27
+ def test_Config(
28
+ tmp_path: Path,
29
+ config: 'Config',
25
30
  ) -> None:
26
31
  """
27
32
  Perform various tests associated with relevant routines.
28
33
 
29
- :param config_path: Custom fixture for populating paths.
34
+ :param tmp_path: pytest object for temporal filesystem.
35
+ :param config: Primary class instance for configuration.
30
36
  """
31
37
 
32
- (config_path
33
- .joinpath('one.yml')
34
- .write_text(
35
- 'enconfig:\n'
36
- f' paths: ["{config_path}"]\n'
37
- 'enlogger:\n'
38
- ' stdo_level: info\n'))
39
-
40
- (config_path
41
- .joinpath('two.yml')
42
- .write_text(
43
- 'encrypts:\n'
44
- ' phrases:\n'
45
- ' default: fernetphrase\n'
46
- 'enlogger:\n'
47
- ' stdo_level: debug\n'
48
- ' file_level: info\n'))
49
-
50
-
51
- config = Config(
52
- files=[
53
- f'{config_path}/one.yml',
54
- f'{config_path}/two.yml'],
55
- cargs={
56
- 'enlogger': {
57
- 'file_level': 'warning'}})
58
38
 
59
39
  attrs = list(config.__dict__)
60
40
 
@@ -68,84 +48,70 @@ def test_Config( # noqa: CFQ001
68
48
  '_Config__crypts']
69
49
 
70
50
 
71
- assert repr(config).startswith(
72
- '<encommon.config.config.Config')
73
- assert isinstance(hash(config), int)
74
- assert str(config).startswith(
75
- '<encommon.config.config.Config')
76
-
51
+ assert repr(config)[:23] == (
52
+ '<encommon.config.config')
77
53
 
78
- assert len(config.files.paths) == 2
79
- assert len(config.paths.paths) == 1
80
- assert len(config.cargs) == 1
81
- assert isinstance(config.config, dict)
82
- assert config.model is Params
83
- assert isinstance(config.params, Params)
54
+ assert hash(config) > 0
84
55
 
56
+ assert str(config)[:23] == (
57
+ '<encommon.config.config')
85
58
 
86
- _config1 = config.config
87
- _config2 = config.config
88
59
 
89
- assert _config1 is not _config2
60
+ assert 'ConfigFiles' in str(config.files)
90
61
 
62
+ assert 'ConfigPaths' in str(config.paths)
91
63
 
92
- sample_path = Path(
93
- f'{SAMPLES}/config.json')
64
+ assert len(config.cargs) == 1
94
65
 
95
- sample = load_sample(
96
- path=sample_path,
97
- update=ENPYRWS,
98
- content=_config1,
99
- replace={
100
- 'config_path': str(config_path)})
66
+ assert len(config.config) == 3
101
67
 
102
- expect = prep_sample(
103
- content=_config2,
104
- replace={
105
- 'config_path': str(config_path)})
68
+ assert config.model is Params
106
69
 
107
- assert sample == expect
70
+ assert isinstance(config.params, Params)
108
71
 
72
+ assert isinstance(config.logger, Logger)
109
73
 
110
- _params1 = config.params
111
- _params2 = config.params
74
+ assert isinstance(config.crypts, Crypts)
112
75
 
113
- assert _params1 is _params2
114
76
 
77
+ replaces = {
78
+ 'pytemp': tmp_path,
79
+ 'PROJECT': PROJECT}
115
80
 
116
- sample_path = Path(
117
- f'{SAMPLES}/params.json')
81
+ sample_path = (
82
+ f'{SAMPLES}/config.json')
118
83
 
119
84
  sample = load_sample(
120
85
  path=sample_path,
121
86
  update=ENPYRWS,
122
- content=_params1.model_dump(),
123
- replace={
124
- 'config_path': str(config_path)})
87
+ content=config.config,
88
+ replace=replaces)
125
89
 
126
90
  expect = prep_sample(
127
- content=_params2.model_dump(),
128
- replace={
129
- 'config_path': str(config_path)})
91
+ content=config.config,
92
+ replace=replaces)
130
93
 
131
94
  assert sample == expect
132
95
 
133
96
 
134
- logger = config.logger
135
97
 
136
- assert isinstance(logger, Logger)
98
+ def test_Config_cover(
99
+ config: 'Config',
100
+ ) -> None:
101
+ """
102
+ Perform various tests associated with relevant routines.
137
103
 
138
- _logger1 = config.logger
139
- _logger2 = config.logger
104
+ :param config: Primary class instance for configuration.
105
+ """
140
106
 
141
- assert _logger1 is _logger2
142
107
 
108
+ logger1 = config.logger
109
+ logger2 = config.logger
143
110
 
144
- crypts = config.crypts
111
+ assert logger1 is logger2
145
112
 
146
- assert isinstance(crypts, Crypts)
147
113
 
148
- _crypts1 = config.crypts
149
- _crypts2 = config.crypts
114
+ crypts1 = config.crypts
115
+ crypts2 = config.crypts
150
116
 
151
- assert _crypts1 is _crypts2
117
+ assert crypts1 is crypts2
@@ -9,12 +9,28 @@ is permitted, for more information consult the project license file.
9
9
 
10
10
  from pathlib import Path
11
11
 
12
+ from pytest import fixture
13
+
12
14
  from . import SAMPLES
13
15
  from ..files import ConfigFile
14
16
  from ..files import ConfigFiles
15
- from ... import ENPYRWS
16
- from ...utils.sample import load_sample
17
- from ...utils.sample import prep_sample
17
+
18
+
19
+
20
+ @fixture
21
+ def files(
22
+ config_path: Path,
23
+ ) -> ConfigFiles:
24
+ """
25
+ Construct the instance for use in the downstream tests.
26
+
27
+ :param config_path: Custom fixture for populating paths.
28
+ :returns: Newly constructed instance of related class.
29
+ """
30
+
31
+ return ConfigFiles([
32
+ f'{SAMPLES}/wayne/bwayne.yml',
33
+ f'{SAMPLES}/stark/tstark.yml'])
18
34
 
19
35
 
20
36
 
@@ -28,78 +44,77 @@ def test_ConfigFile(
28
44
  """
29
45
 
30
46
  file = ConfigFile(
31
- f'{config_path}/wayne/bwayne.yml')
47
+ f'{config_path}/config.yml')
48
+
32
49
 
33
50
  attrs = list(file.__dict__)
34
51
 
35
- assert attrs == ['path', 'config']
52
+ assert attrs == [
53
+ 'path',
54
+ 'config']
55
+
36
56
 
57
+ assert repr(file)[:22] == (
58
+ '<encommon.config.files')
37
59
 
38
- assert repr(file).startswith(
39
- '<encommon.config.files.ConfigFile')
40
- assert isinstance(hash(file), int)
41
- assert str(file).startswith(
42
- '<encommon.config.files.ConfigFile')
60
+ assert hash(file) > 0
43
61
 
62
+ assert str(file)[:22] == (
63
+ '<encommon.config.files')
44
64
 
45
- assert file.path.name == 'bwayne.yml'
46
- assert list(file.config) == ['name']
65
+
66
+ assert file.path.name == 'config.yml'
67
+
68
+ assert len(file.config) == 3
47
69
 
48
70
 
49
71
 
50
72
  def test_ConfigFiles(
51
- config_path: Path,
73
+ files: ConfigFiles,
52
74
  ) -> None:
53
75
  """
54
76
  Perform various tests associated with relevant routines.
55
77
 
56
- :param config_path: Custom fixture for populating paths.
78
+ :param files: Custom fixture for the configuration files.
57
79
  """
58
80
 
59
- files = ConfigFiles([
60
- f'{config_path}/wayne/bwayne.yml',
61
- f'{config_path}/stark/tstark.yml'])
62
81
 
63
82
  attrs = list(files.__dict__)
64
83
 
65
84
  assert attrs == [
66
- 'paths', 'config',
85
+ 'paths',
86
+ 'config',
67
87
  '_ConfigFiles__merged']
68
88
 
69
89
 
70
- assert repr(files).startswith(
71
- '<encommon.config.files.ConfigFiles')
72
- assert isinstance(hash(files), int)
73
- assert str(files).startswith(
74
- '<encommon.config.files.ConfigFiles')
90
+ assert repr(files)[:22] == (
91
+ '<encommon.config.files')
75
92
 
93
+ assert hash(files) > 0
76
94
 
77
- assert len(files.paths) == 2
78
- assert len(files.config) == 2
95
+ assert str(files)[:22] == (
96
+ '<encommon.config.files')
79
97
 
80
98
 
81
- files = ConfigFiles(
82
- f'{config_path}/wayne/bwayne.yml')
99
+ assert len(files.paths) == 2
83
100
 
101
+ assert len(files.config) == 2
102
+
103
+ assert files.merged == {
104
+ 'name': 'Bruce Wayne'}
84
105
 
85
- _merged1 = files.merged
86
- _merged2 = files.merged
87
106
 
88
- assert _merged1 is not _merged2
89
107
 
90
- sample_path = Path(
91
- f'{SAMPLES}/files.json')
108
+ def test_ConfigFiles_cover(
109
+ files: ConfigFiles,
110
+ ) -> None:
111
+ """
112
+ Perform various tests associated with relevant routines.
92
113
 
93
- sample = load_sample(
94
- path=sample_path,
95
- update=ENPYRWS,
96
- content=_merged1,
97
- replace={
98
- 'config_path': str(config_path)})
114
+ :param files: Custom fixture for the configuration files.
115
+ """
99
116
 
100
- expect = prep_sample(
101
- content=_merged2,
102
- replace={
103
- 'config_path': str(config_path)})
117
+ merged1 = files.merged
118
+ merged2 = files.merged
104
119
 
105
- assert sample == expect
120
+ assert merged1 is not merged2
@@ -7,15 +7,42 @@ is permitted, for more information consult the project license file.
7
7
 
8
8
 
9
9
 
10
- from logging import Logger as _Logger
11
10
  from pathlib import Path
12
11
 
13
12
  from _pytest.logging import LogCaptureFixture
14
13
 
14
+ from pytest import fixture
15
+
15
16
  from ..logger import Logger
16
17
  from ..logger import Message
18
+ from ..params import LoggerParams
17
19
  from ...times.common import UNIXMPOCH
18
- from ...utils.stdout import strip_ansi
20
+ from ...times.common import UNIXSPOCH
21
+ from ...utils import strip_ansi
22
+
23
+
24
+
25
+ _CAPLOG = list[tuple[str, int, str]]
26
+
27
+
28
+
29
+ @fixture
30
+ def logger(
31
+ tmp_path: Path,
32
+ ) -> Logger:
33
+ """
34
+ Construct the instance for use in the downstream tests.
35
+
36
+ :param tmp_path: pytest object for temporal filesystem.
37
+ :returns: Newly constructed instance of related class.
38
+ """
39
+
40
+ params = LoggerParams(
41
+ stdo_level='info',
42
+ file_level='info',
43
+ file_path=f'{tmp_path}/test.log')
44
+
45
+ return Logger(params=params)
19
46
 
20
47
 
21
48
 
@@ -24,18 +51,21 @@ def test_Message() -> None:
24
51
  Perform various tests associated with relevant routines.
25
52
  """
26
53
 
27
-
28
54
  message = Message(
29
55
  time=UNIXMPOCH,
30
56
  level='info',
31
- dict={'foo': 'bar'},
32
- empty=[],
33
- float=1.0,
34
- int=1,
35
- list=[1, '2', 3],
57
+ string='foobar',
36
58
  none=None,
37
- string='foo',
38
- elapsed=0.69420)
59
+ list=['1', 2],
60
+ tuple=('1', 2),
61
+ set={'1', 2},
62
+ dict={'1': 2},
63
+ empty_list=[],
64
+ empty_dict={},
65
+ int=1,
66
+ float=2.0,
67
+ elapsed=3.69420)
68
+
39
69
 
40
70
  attrs = list(message.__dict__)
41
71
 
@@ -45,81 +75,66 @@ def test_Message() -> None:
45
75
  '_Message__fields']
46
76
 
47
77
 
48
- assert repr(message).startswith(
49
- 'Message(level="info", time="1970')
50
- assert isinstance(hash(message), int)
51
- assert str(message).startswith(
52
- 'Message(level="info", time="1970')
53
-
78
+ assert repr(message)[:20] == (
79
+ 'Message(level="info"')
54
80
 
55
- assert repr(message) == (
56
- 'Message('
57
- 'level="info", '
58
- f'time="{UNIXMPOCH}", '
59
- 'dict="{\'foo\': \'bar\'}", '
60
- 'float="1.0", '
61
- 'int="1", '
62
- 'list="[1, \'2\', 3]", '
63
- 'string="foo", '
64
- 'elapsed="0.69")')
81
+ assert hash(message) > 0
65
82
 
66
- assert str(message) == repr(message)
83
+ assert str(message)[:20] == (
84
+ 'Message(level="info"')
67
85
 
68
86
 
69
87
  assert message.level == 'info'
70
- assert message.time == '1970-01-01'
71
88
 
72
- assert message.fields == {
73
- 'dict': "{'foo': 'bar'}",
74
- 'float': '1.0',
75
- 'int': '1',
76
- 'list': "[1, '2', 3]",
77
- 'string': 'foo',
78
- 'elapsed': '0.69'}
89
+ assert message.time == 0
90
+
91
+ assert len(message.fields) == 8
79
92
 
80
93
 
81
- output = strip_ansi(message.stdo_output)
94
+ output = strip_ansi(
95
+ message.stdo_output)
82
96
 
83
97
  assert output == (
84
98
  'level="info"'
85
- ' time="1970-01-01T00:00:00Z"'
86
- ' dict="{\'foo\': \'bar\'}"'
87
- ' float="1.0"'
99
+ f' time="{UNIXSPOCH}"'
100
+ ' string="foobar"'
101
+ ' list="1,2"'
102
+ ' tuple="1,2"'
103
+ ' set="1,2"'
104
+ ' dict="{\'1\': 2}"'
88
105
  ' int="1"'
89
- ' list="[1, \'2\', 3]"'
90
- ' string="foo"'
91
- ' elapsed="0.69"')
106
+ ' float="2.0"'
107
+ ' elapsed="3.69"')
92
108
 
93
109
 
94
- assert message.file_output == (
110
+ output = message.file_output
111
+
112
+ assert output == (
95
113
  '{"level": "info",'
96
114
  f' "time": "{UNIXMPOCH}",'
97
- ' "dict": "{\'foo\': \'bar\'}",'
98
- ' "float": "1.0",'
115
+ ' "string": "foobar",'
116
+ ' "list": "1,2",'
117
+ ' "tuple": "1,2",'
118
+ ' "set": "1,2",'
119
+ ' "dict": "{\'1\': 2}",'
99
120
  ' "int": "1",'
100
- ' "list": "[1, \'2\', 3]",'
101
- ' "string": "foo",'
102
- ' "elapsed": "0.69"}')
121
+ ' "float": "2.0",'
122
+ ' "elapsed": "3.69"}')
103
123
 
104
124
 
105
125
 
106
126
  def test_Logger(
107
- tmp_path: Path,
127
+ logger: Logger,
108
128
  caplog: LogCaptureFixture,
109
129
  ) -> None:
110
130
  """
111
131
  Perform various tests associated with relevant routines.
112
132
 
113
- :param tmp_path: pytest object for temporal filesystem.
133
+ :param logger: Custom fixture for the logger instance.
114
134
  :param caplog: pytest object for capturing log message.
115
135
  """
116
136
 
117
137
 
118
- logger = Logger(
119
- stdo_level='info',
120
- file_level='info',
121
- file_path=f'{tmp_path}/test.log')
122
-
123
138
  attrs = list(logger.__dict__)
124
139
 
125
140
  assert attrs == [
@@ -127,47 +142,78 @@ def test_Logger(
127
142
  '_Logger__file_level',
128
143
  '_Logger__file_path',
129
144
  '_Logger__started',
130
- '_Logger__logger_stdo',
131
- '_Logger__logger_file']
145
+ '_Logger__logr_stdo',
146
+ '_Logger__logr_file']
147
+
148
+
149
+ assert repr(logger)[:23] == (
150
+ '<encommon.config.logger')
132
151
 
152
+ assert hash(logger) > 0
133
153
 
134
- assert repr(logger).startswith(
135
- '<encommon.config.logger.Logger')
136
- assert isinstance(hash(logger), int)
137
- assert str(logger).startswith(
138
- '<encommon.config.logger.Logger')
154
+ assert str(logger)[:23] == (
155
+ '<encommon.config.logger')
139
156
 
140
157
 
141
158
  assert logger.stdo_level == 'info'
159
+
142
160
  assert logger.file_level == 'info'
161
+
143
162
  assert logger.file_path is not None
144
- assert logger.file_path.name == 'test.log'
163
+
145
164
  assert logger.started is False
146
- assert isinstance(logger.logger_stdo, _Logger)
147
- assert isinstance(logger.logger_file, _Logger)
165
+
166
+ assert logger.logger_stdo is not None
167
+
168
+ assert logger.logger_file is not None
169
+
170
+
171
+ logger.log_d(msg='pytest')
172
+ logger.log_c(msg='pytest')
173
+ logger.log_e(msg='pytest')
174
+ logger.log_i(msg='pytest')
175
+ logger.log_w(msg='pytest')
176
+
177
+
178
+
179
+ def test_Logger_cover(
180
+ logger: Logger,
181
+ caplog: LogCaptureFixture,
182
+ ) -> None:
183
+ """
184
+ Perform various tests associated with relevant routines.
185
+
186
+ :param logger: Custom fixture for the logger instance.
187
+ :param caplog: pytest object for capturing log message.
188
+ """
148
189
 
149
190
 
150
191
  def _logger_logs() -> None:
151
- logger.log_d(message='pytest')
152
- logger.log_c(message='pytest')
153
- logger.log_e(message='pytest')
154
- logger.log_i(message='pytest')
155
- logger.log_w(message='pytest')
192
+ logger.log_d(msg='pytest')
193
+ logger.log_c(msg='pytest')
194
+ logger.log_e(msg='pytest')
195
+ logger.log_i(msg='pytest')
196
+ logger.log_w(msg='pytest')
156
197
 
157
198
 
158
- _caplog = list[tuple[str, int, str]]
199
+ def _logger_stdo() -> _CAPLOG:
159
200
 
201
+ output = caplog.record_tuples
202
+ key = 'encommon.logger.stdo'
160
203
 
161
- def _logger_stdo() -> _caplog:
162
204
  return [
163
- x for x in caplog.record_tuples
164
- if x[0] == 'encommon.logger.stdo']
205
+ x for x in output
206
+ if x[0] == key]
207
+
208
+
209
+ def _logger_file() -> _CAPLOG:
165
210
 
211
+ output = caplog.record_tuples
212
+ key = 'encommon.logger.file'
166
213
 
167
- def _logger_file() -> _caplog:
168
214
  return [
169
- x for x in caplog.record_tuples
170
- if x[0] == 'encommon.logger.file']
215
+ x for x in output
216
+ if x[0] == key]
171
217
 
172
218
 
173
219
  logger.start()
@@ -189,16 +235,17 @@ def test_Logger(
189
235
  logger.start()
190
236
 
191
237
  message = 'unknown exception'
238
+ raises = Exception('pytest')
192
239
 
193
240
  logger.log_e(
194
241
  message=message,
195
- exc_info=Exception('pytest'))
242
+ exc_info=raises)
196
243
 
197
- stdo_text = _logger_stdo()[-1][2]
198
- file_text = _logger_file()[-1][2]
244
+ stdo = _logger_stdo()[-1][2]
245
+ file = _logger_file()[-1][2]
199
246
 
200
- assert message in str(stdo_text)
201
- assert message in str(file_text)
247
+ assert message in str(stdo)
248
+ assert message in str(file)
202
249
 
203
250
  assert len(_logger_stdo()) == 6
204
251
  assert len(_logger_file()) == 6